{
  "openapi": "3.1.0",
  "info": {
    "title": "Sendly API",
    "version": "1.0.0",
    "description": "The Sendly REST API: its public operations, and its preview operations (x-stability-level: alpha), which may still change. Generated from Sendly's API contract; do not edit by hand."
  },
  "servers": [
    {
      "url": "https://sendly.live",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "10DLC brands and campaigns",
      "description": "Register a business and its messaging campaigns for carrier review, then assign US local numbers to an approved campaign so they can send."
    },
    {
      "name": "AI message enhancement",
      "description": "Rewrite a draft SMS into a clear, professional message of at most 160 characters before you send it."
    },
    {
      "name": "Account and API keys",
      "description": "Read the account, its workspace and credit balance, and create, rotate, rename and revoke its API keys."
    },
    {
      "name": "Auto-label rules",
      "description": "Rules that label or close a conversation when the classifier's intent and sentiment for an inbound message match them."
    },
    {
      "name": "Business entity upgrade",
      "description": "Move a verified workspace to a new legal entity with its own toll-free number, while the current number keeps sending until the new one is approved."
    },
    {
      "name": "Business upgrade preflight",
      "description": "Check the business details a business upgrade would submit before submitting them, and prefill them from the caller's verified businesses."
    },
    {
      "name": "Calls",
      "description": "Place phone calls that the workspace's AI agents handle, list and inspect calls, end one, and fetch its recording."
    },
    {
      "name": "Campaigns",
      "description": "Create bulk SMS campaigns to a contact list, every contact or a list of numbers, preview their reach and cost, and send or schedule them."
    },
    {
      "name": "Contact lists",
      "description": "Group a workspace's contacts into named lists, to send campaigns to, and add or remove their members."
    },
    {
      "name": "Contacts",
      "description": "Keep the workspace's contacts: create, import, update and delete them, opt numbers out, and check which numbers can receive texts."
    },
    {
      "name": "Conversations",
      "description": "Read a workspace's message threads with each contact, reply to them, label, close and reopen them, and turn them into context for a language model."
    },
    {
      "name": "Countries",
      "description": "The countries Sendly sends SMS to, with the price tier and price per SMS segment of each. Public: no API key needed."
    },
    {
      "name": "Credits",
      "description": "Read the credit balance a key spends from and its transaction history, and move credits between workspaces you own."
    },
    {
      "name": "Drafts",
      "description": "Save replies to a conversation for a person to review, then approve them to send or reject them."
    },
    {
      "name": "Enterprise workspaces",
      "description": "Run many workspaces from one enterprise account with an enterprise master key: provision, manage and suspend workspaces, their verification, credits, quotas, keys, team invitations, hosted pages and webhooks, and read analytics and billing across them."
    },
    {
      "name": "Events",
      "description": "Stream a workspace's real-time events, such as new messages and delivery statuses, over Server-Sent Events."
    },
    {
      "name": "Labels",
      "description": "Create, list and delete the labels a workspace tags its conversations and messages with. Behind the `conversations_api` flag."
    },
    {
      "name": "Media",
      "description": "Upload images to send as MMS, list them, and delete them."
    },
    {
      "name": "Message templates",
      "description": "Reusable SMS texts with `{{key}}` variables: your own drafts and published templates, and Sendly's presets."
    },
    {
      "name": "Messaging",
      "description": "Send SMS, MMS, WhatsApp and RCS messages, schedule them, send them in batches and to groups, label them, and read the messages a workspace has sent and received."
    },
    {
      "name": "Number porting",
      "description": "Check whether numbers can be ported in, start a full port of a US or Canada number, and follow, submit or cancel it."
    },
    {
      "name": "Phone numbers",
      "description": "Search, buy and release the phone numbers a workspace sends from, and list the ones it owns."
    },
    {
      "name": "RCS channel",
      "description": "Register an RCS brand and agent, invite test devices, submit for review, request launch, and check whether a number can receive RCS. Behind the `rcs_channel` flag."
    },
    {
      "name": "Short codes",
      "description": "Apply for a US short code and follow the application through Sendly's review and each carrier's certification. Behind the `short_codes` flag: without it every operation answers 404 `short_codes_not_enabled`."
    },
    {
      "name": "Short links",
      "description": "Mint branded short links that redirect to a URL and count their clicks, list them, and switch one off or back on. Behind the `url_shortener` flag."
    },
    {
      "name": "Verification and OTP",
      "description": "Send one-time codes by SMS and check them, keep verify profiles with the defaults for sending codes, and run the hosted verification page."
    },
    {
      "name": "Voice",
      "description": "Configure what phone calls depend on: switch voice on for a number and choose how it answers, register its emergency address, and manage the AI agents that answer and place calls."
    },
    {
      "name": "Webhooks",
      "description": "Register endpoints that receive signed events, read and retry their deliveries, and recover events missed during an outage."
    },
    {
      "name": "WhatsApp channel",
      "description": "Connect workspace numbers to WhatsApp, manage their business profiles, calling and message templates, and check the 24-hour window. Behind the `whatsapp_channel` flag: while it is off for the account, every operation answers 404."
    }
  ],
  "paths": {
    "/api/v1/account": {
      "get": {
        "operationId": "getAccount",
        "summary": "Get the account",
        "description": "Returns the key's user, workspace, credit balance, business verification and the calling key itself.",
        "tags": [
          "Account and API keys"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- Account: The account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "examples": {
                  "default": {
                    "summary": "The test key's account: a personal key, so no workspace.",
                    "value": {
                      "user": {
                        "id": "00000000-0000-4000-8000-000000000001",
                        "email": "user@example.com",
                        "createdAt": "2026-01-01T00:00:00.000Z"
                      },
                      "organization": null,
                      "credits": {
                        "balance": 170,
                        "reservedBalance": "0"
                      },
                      "verification": {
                        "status": "verified",
                        "type": "both",
                        "region": "both",
                        "submittedAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      },
                      "apiKey": {
                        "id": "00000000-0000-4000-8000-000000000002",
                        "name": "sdk-e2e-smoke (temporary)",
                        "type": "test",
                        "scopes": [
                          "sms:read"
                        ],
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "lastUsedAt": "2026-01-01T00:00:00.000Z"
                      },
                      "limits": {
                        "messagesPerMinute": 60,
                        "messagesPerDay": 100
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `user_not_found`: The key's user no longer exists.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "user_not_found"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "user_not_found",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "user_not_found"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The account could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/credits": {
      "get": {
        "operationId": "getAccountCredits",
        "summary": "Get the credit balance and recent transactions",
        "description": "Returns the balance the key's workspace spends, from its own balance or its enterprise pool, with its 20 most recent credit transactions.",
        "tags": [
          "Account and API keys"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- AccountCredits: The balance and recent transactions.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCredits"
                },
                "examples": {
                  "default": {
                    "summary": "The test key's balance and recent credit transactions.",
                    "value": {
                      "balance": 170,
                      "reservedBalance": 0,
                      "availableBalance": 170,
                      "billingMode": "prepaid",
                      "recentTransactions": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The credits could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/keys": {
      "get": {
        "operationId": "listApiKeys",
        "summary": "List API keys",
        "description": "Lists every API key of the key's workspace, revoked ones included, newest first. A personal key lists the user's personal keys.",
        "tags": [
          "Account and API keys"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "listApiKeys"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- ApiKeyList: The keys.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyList"
                },
                "examples": {
                  "default": {
                    "summary": "The personal keys of the test key's user.",
                    "value": {
                      "keys": [
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "name": "sdk-e2e-smoke (temporary)",
                          "type": "test",
                          "prefix": "sk_test_v1_placeholder...",
                          "scopes": [
                            "sms:read"
                          ],
                          "permissions": [
                            "sms:read"
                          ],
                          "isActive": true,
                          "isRevoked": false,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "lastUsedAt": "2026-01-01T00:00:00.000Z",
                          "expiresAt": null
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000003",
                          "name": "Enterprise Master Key (rotated)",
                          "type": "live",
                          "prefix": "sk_test_v1_placeholder...",
                          "scopes": [
                            "enterprise:master",
                            "numbers:read",
                            "numbers:write"
                          ],
                          "permissions": [
                            "enterprise:master",
                            "numbers:read",
                            "numbers:write"
                          ],
                          "isActive": true,
                          "isRevoked": false,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "lastUsedAt": "2026-01-01T00:00:00.000Z",
                          "expiresAt": null
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000004",
                          "name": "Enterprise Master Key",
                          "type": "live",
                          "prefix": "sk_test_v1_placeholder...",
                          "scopes": [
                            "enterprise:master",
                            "numbers:read",
                            "numbers:write"
                          ],
                          "permissions": [
                            "enterprise:master",
                            "numbers:read",
                            "numbers:write"
                          ],
                          "isActive": true,
                          "isRevoked": false,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "lastUsedAt": "2026-01-01T00:00:00.000Z",
                          "expiresAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000005",
                          "name": "Enterprise Master Key (rotated)",
                          "type": "live",
                          "prefix": "sk_test_v1_placeholder...",
                          "scopes": [
                            "enterprise:master"
                          ],
                          "permissions": [
                            "enterprise:master"
                          ],
                          "isActive": false,
                          "isRevoked": true,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "lastUsedAt": null,
                          "expiresAt": null
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000006",
                          "name": "Enterprise Master Key",
                          "type": "live",
                          "prefix": "sk_test_v1_placeholder...",
                          "scopes": [
                            "enterprise:master"
                          ],
                          "permissions": [
                            "enterprise:master"
                          ],
                          "isActive": false,
                          "isRevoked": true,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "lastUsedAt": null,
                          "expiresAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key passed in the URL.",
                    "value": {
                      "error": "invalid_request",
                      "message": "API keys must not be passed in URL parameters. Use the Authorization header instead."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The keys could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createApiKey",
        "summary": "Create an API key",
        "description": "Creates a key in the calling key's workspace, with at most the calling key's scopes. The secret is in the response only. The account owner gets an email, unless they turned that off.",
        "tags": [
          "Account and API keys"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "createApiKey"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The key to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- CreatedApiKey: The key was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedApiKey"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and formatCreatedApiKey, not captured: creating a key emails the account owner. A test key with one scope and no expiry.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000100",
                      "name": "Staging",
                      "key": "sk_test_v1_placeholder",
                      "keyPrefix": "sk_test_v1_placeholder",
                      "type": "test",
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "expiresAt": null,
                      "apiKey": {
                        "id": "00000000-0000-4000-8000-000000000100",
                        "name": "Staging",
                        "type": "test",
                        "prefix": "sk_test_v1_placeholder...",
                        "scopes": [
                          "sms:read"
                        ],
                        "permissions": [
                          "sms:read"
                        ],
                        "isActive": true,
                        "isRevoked": false,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "lastUsedAt": null,
                        "expiresAt": null
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `validation_error`: `name` is missing or empty, `type` is not `test` or `live`, `expiresAt` is not a time or is not in the future, or `scopes` is not an array of known scopes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "expired": {
                    "summary": "An expiry in the past.",
                    "value": {
                      "error": "validation_error",
                      "message": "expiresAt must be in the future"
                    }
                  },
                  "invalid-scopes": {
                    "summary": "A scope the API does not have.",
                    "value": {
                      "error": "validation_error",
                      "message": "Invalid scopes. Allowed: sms:send, sms:read, verify:send, verify:read, webhooks:read, webhooks:write, templates:read, templates:write, campaigns:read, campaigns:write, campaigns:send, contacts:read, contacts:write, numbers:read, numbers:write, tendlc:read, tendlc:write, rcs:read, rcs:write, whatsapp:read, whatsapp:write, short_codes:read, short_codes:write, calls:read, calls:write"
                    }
                  },
                  "invalid-type": {
                    "summary": "A type that is neither test nor live.",
                    "value": {
                      "error": "validation_error",
                      "message": "Type must be 'test' or 'live'"
                    }
                  },
                  "default": {
                    "summary": "No name.",
                    "value": {
                      "error": "validation_error",
                      "message": "Name is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `credits_required`: A `live` key was asked for, and the workspace (or its enterprise pool, with the overage cap) has no credits.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "credits_required"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "credits_required",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "credits_required"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `verification_required`: A `live` key was asked for, and the business is not verified.\n- `insufficient_permissions`: `scopes` names a scope the calling key does not hold, or `scopes` is absent and the calling key holds none it could grant. A test key asking for a `live` key gets this too, with a `hint` that says to create the first live key in the dashboard or a signed-in CLI; a CLI session may create one.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "verification_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "verification_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "verification_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A scope the calling key, which holds only sms:read, does not hold.",
                    "value": {
                      "error": "insufficient_permissions",
                      "message": "This API key cannot grant scopes it does not have: calls:write"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The key could not be created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/keys/{id}": {
      "get": {
        "operationId": "getApiKey",
        "summary": "Get an API key",
        "description": "Returns one key, without its secret. A workspace key reads its workspace's keys; a personal key reads any key of its user.",
        "tags": [
          "Account and API keys"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "getApiKey"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The API key's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ApiKeyDetail: The key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyDetail"
                },
                "examples": {
                  "default": {
                    "summary": "The test key itself, in its rotation grace period.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "name": "sdk-e2e-smoke (temporary)",
                      "type": "test",
                      "prefix": "sk_test_v1_placeholder...",
                      "scopes": [
                        "sms:read"
                      ],
                      "isActive": true,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "lastUsedAt": "2026-01-01T00:00:00.000Z",
                      "expiresAt": "2026-01-01T00:00:00.000Z",
                      "revokedAt": null
                    }
                  },
                  "revoked": {
                    "summary": "The revoked replacement key.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000007",
                      "name": "e2e-probe-contract-account",
                      "type": "test",
                      "prefix": "sk_test_v1_placeholder...",
                      "scopes": [
                        "sms:read"
                      ],
                      "isActive": false,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "lastUsedAt": null,
                      "expiresAt": null,
                      "revokedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No key with this id belongs to the workspace, or to the user for a personal key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no key.",
                    "value": {
                      "error": "not_found",
                      "message": "API key not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The key could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/keys/{id}/rename": {
      "patch": {
        "operationId": "renameApiKey",
        "summary": "Rename an API key",
        "tags": [
          "Account and API keys"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "renameApiKey"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The API key's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The new name.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ApiKey: The renamed key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                },
                "examples": {
                  "default": {
                    "summary": "The replacement key, renamed.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000007",
                      "name": "e2e-probe-contract-account",
                      "type": "test",
                      "prefix": "sk_test_v1_placeholder...",
                      "scopes": [
                        "sms:read"
                      ],
                      "permissions": [
                        "sms:read"
                      ],
                      "isActive": true,
                      "isRevoked": false,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "lastUsedAt": null,
                      "expiresAt": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `validation_error`: `name` is missing, not a string, or empty.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A name of only spaces.",
                    "value": {
                      "error": "validation_error",
                      "message": "Name is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `insufficient_permissions`: The target key belongs to the caller's workspace (or user, for a personal key) and is stronger than the calling key: it holds a scope the calling key lacks, or it is a live key and the caller a test key. A CLI session skips this check.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No key with this id belongs to the workspace, or for a personal key, to the user's personal keys.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no key.",
                    "value": {
                      "error": "not_found",
                      "message": "API key not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The target key could not be read.\n- `internal_error`: The key could not be renamed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/keys/{id}/revoke": {
      "patch": {
        "operationId": "revokeApiKey",
        "summary": "Revoke an API key",
        "description": "Revokes a key at once. Revoking a key that is already revoked answers 200 again, with a new `revokedAt`. A key may only revoke a key no stronger than itself.",
        "tags": [
          "Account and API keys"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "revokeApiKey"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The API key's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "Optional. Why the key is revoked.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- RevokedApiKey: The key was revoked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevokedApiKey"
                },
                "examples": {
                  "default": {
                    "summary": "The replacement key, revoked.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000007",
                      "name": "e2e-probe-contract-account",
                      "revoked": true,
                      "revokedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `self_revoke`: The id is the calling key's own.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "self_revoke"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "self_revoke",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "self_revoke"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The calling key's own id.",
                    "value": {
                      "error": "self_revoke",
                      "message": "Cannot revoke the API key currently in use"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `insufficient_permissions`: The target key belongs to the caller's workspace (or user, for a personal key) and is stronger than the calling key: it holds a scope the calling key lacks, or it is a live key and the caller a test key. A CLI session skips this check.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No key with this id belongs to the workspace, or to the user's personal keys for a personal key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: an id that matches no key. Since main's #204 (31e3c657) storage throws \"API key not found\" for it, and revokeApiKeyV1 answers 404. The production capture of 2026-10-03 predates that change and answered 500 internal_error.",
                    "value": {
                      "error": "not_found",
                      "message": "API key not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The target key could not be read.\n- `internal_error`: The key could not be revoked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/keys/{id}/rotate": {
      "post": {
        "operationId": "rotateApiKey",
        "summary": "Rotate an API key",
        "description": "Issues a replacement key with the same type and scopes, and makes the old key expire after a grace period, so running code keeps working. A key stored with no scopes rotates to a key with an empty `scopes` list. A workspace key rotates its workspace's keys; a personal key rotates any key of its user. A key may only rotate a key no stronger than itself, and an enterprise master key is rotated from the enterprise dashboard instead.",
        "tags": [
          "Account and API keys"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "rotateApiKey"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The API key's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "Optional. The grace period.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RotateApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- RotatedApiKey: The key was rotated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotatedApiKey"
                },
                "examples": {
                  "default": {
                    "summary": "The test key rotates itself: a replacement test key, and the old one expires in 24 hours.",
                    "value": {
                      "newKey": {
                        "id": "00000000-0000-4000-8000-000000000007",
                        "userId": "00000000-0000-4000-8000-000000000001",
                        "organizationId": null,
                        "name": "sdk-e2e-smoke (temporary) (rotated)",
                        "keyId": "key_placeholder1",
                        "keyPrefix": "sk_test_v1_placeholder",
                        "type": "test",
                        "scopes": [
                          "sms:read"
                        ],
                        "source": "manual",
                        "expiresAt": null,
                        "lastUsedAt": null,
                        "isActive": true,
                        "revokedAt": null,
                        "revokedReason": null,
                        "rotatedFromId": "00000000-0000-4000-8000-000000000002",
                        "gracePeriodHours": 24,
                        "isEnterpriseMaster": false,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "key": "sk_test_v1_placeholder",
                        "warning": "This key will only be shown once. Store it securely."
                      },
                      "oldKey": {
                        "id": "00000000-0000-4000-8000-000000000002",
                        "userId": "00000000-0000-4000-8000-000000000001",
                        "organizationId": null,
                        "name": "sdk-e2e-smoke (temporary)",
                        "keyId": "key_placeholder2",
                        "keyPrefix": "sk_test_v1_placeholder",
                        "type": "test",
                        "scopes": [
                          "sms:read"
                        ],
                        "source": "manual",
                        "expiresAt": "2026-01-01T00:00:00.000Z",
                        "lastUsedAt": "2026-01-01T00:00:00.000Z",
                        "isActive": true,
                        "revokedAt": null,
                        "revokedReason": null,
                        "rotatedFromId": null,
                        "gracePeriodHours": 24,
                        "isEnterpriseMaster": false,
                        "createdAt": "2026-01-01T00:00:00.000Z"
                      },
                      "message": "Old key will expire in 24 hours"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `gracePeriodHours` is not a number, is below 24 or is above 168.\n- `invalid_state`: The key is revoked or inactive, or is an enterprise master key.\n- `already_rotating`: The key has an expiry in the future: it is already being rotated, or was created to expire.\n- `predecessor_in_grace`: The key replaced another key that is still in its grace period.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_state"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_state",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_state"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "already_rotating"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "expiresAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the key's current grace period ends. ISO 8601, in UTC."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "expiresAt"
                      ],
                      "title": "already_rotating",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "already_rotating"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "predecessor_in_grace"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "predecessorExpiresAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the key this one replaced stops working. ISO 8601, in UTC."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "predecessorExpiresAt"
                      ],
                      "title": "predecessor_in_grace",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "predecessor_in_grace"
                      ]
                    }
                  ]
                },
                "examples": {
                  "already-rotating": {
                    "summary": "The test key again, while its grace period runs.",
                    "value": {
                      "error": "already_rotating",
                      "message": "This key is already being rotated. Wait for the grace period to expire before rotating again.",
                      "expiresAt": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "default": {
                    "summary": "A grace period shorter than 24 hours.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Grace period must be at least 24 hours"
                    }
                  },
                  "predecessor-in-grace": {
                    "summary": "The replacement key, while the key it replaced is in its grace period.",
                    "value": {
                      "error": "predecessor_in_grace",
                      "message": "Cannot rotate this key while its predecessor is still in its grace period.",
                      "predecessorExpiresAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `insufficient_permissions`: The target key belongs to the caller's workspace (or user, for a personal key) and is stronger than the calling key: it holds a scope the calling key lacks, or it is a live key and the caller a test key. A CLI session skips this check.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No key with this id belongs to the workspace, or to the user for a personal key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no key.",
                    "value": {
                      "error": "not_found",
                      "message": "API key not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The target key could not be read.\n- `internal_error`: The key could not be rotated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/keys/{id}/usage": {
      "get": {
        "operationId": "getApiKeyUsage",
        "summary": "Get an API key's usage",
        "description": "Summarizes the key's 100 most recent requests and lists the 20 newest. A workspace key reads its workspace's keys; a personal key reads any key of its user.",
        "tags": [
          "Account and API keys"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "getApiKeyUsage"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The API key's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ApiKeyUsage: The key's usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyUsage"
                },
                "examples": {
                  "default": {
                    "summary": "The test key's requests in this capture.",
                    "value": {
                      "keyId": "00000000-0000-4000-8000-000000000002",
                      "keyName": "sdk-e2e-smoke (temporary)",
                      "summary": {
                        "totalRequests": 22,
                        "totalCredits": 0,
                        "lastUsed": "2026-01-01T00:00:00.000Z"
                      },
                      "recentRequests": [
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000000",
                          "method": "GET",
                          "statusCode": 404,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000007",
                          "method": "GET",
                          "statusCode": 200,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000002",
                          "method": "GET",
                          "statusCode": 200,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000000/revoke",
                          "method": "PATCH",
                          "statusCode": 500,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000007/revoke",
                          "method": "PATCH",
                          "statusCode": 200,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000002/revoke",
                          "method": "PATCH",
                          "statusCode": 400,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000000/rename",
                          "method": "PATCH",
                          "statusCode": 404,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000002/rename",
                          "method": "PATCH",
                          "statusCode": 400,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000007/rename",
                          "method": "PATCH",
                          "statusCode": 200,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000007/rotate",
                          "method": "POST",
                          "statusCode": 400,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000002/rotate",
                          "method": "POST",
                          "statusCode": 400,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000002/rotate",
                          "method": "POST",
                          "statusCode": 200,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000000/rotate",
                          "method": "POST",
                          "statusCode": 404,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys/00000000-0000-4000-8000-000000000002/rotate",
                          "method": "POST",
                          "statusCode": 400,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys",
                          "method": "POST",
                          "statusCode": 403,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys",
                          "method": "POST",
                          "statusCode": 400,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys",
                          "method": "POST",
                          "statusCode": 400,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys",
                          "method": "POST",
                          "statusCode": 400,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys",
                          "method": "POST",
                          "statusCode": 400,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "endpoint": "/api/v1/account/keys",
                          "method": "GET",
                          "statusCode": 200,
                          "creditsUsed": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        }
                      ],
                      "endpointBreakdown": [
                        {
                          "endpoint": "POST /api/v1/account/keys",
                          "count": 5
                        },
                        {
                          "endpoint": "POST /api/v1/account/keys/00000000-0000-4000-8000-000000000002/rotate",
                          "count": 3
                        },
                        {
                          "endpoint": "GET /api/v1/account/keys/00000000-0000-4000-8000-000000000000",
                          "count": 1
                        },
                        {
                          "endpoint": "GET /api/v1/account/keys/00000000-0000-4000-8000-000000000007",
                          "count": 1
                        },
                        {
                          "endpoint": "GET /api/v1/account/keys/00000000-0000-4000-8000-000000000002",
                          "count": 1
                        },
                        {
                          "endpoint": "PATCH /api/v1/account/keys/00000000-0000-4000-8000-000000000000/revoke",
                          "count": 1
                        },
                        {
                          "endpoint": "PATCH /api/v1/account/keys/00000000-0000-4000-8000-000000000007/revoke",
                          "count": 1
                        },
                        {
                          "endpoint": "PATCH /api/v1/account/keys/00000000-0000-4000-8000-000000000002/revoke",
                          "count": 1
                        },
                        {
                          "endpoint": "PATCH /api/v1/account/keys/00000000-0000-4000-8000-000000000000/rename",
                          "count": 1
                        },
                        {
                          "endpoint": "PATCH /api/v1/account/keys/00000000-0000-4000-8000-000000000002/rename",
                          "count": 1
                        },
                        {
                          "endpoint": "PATCH /api/v1/account/keys/00000000-0000-4000-8000-000000000007/rename",
                          "count": 1
                        },
                        {
                          "endpoint": "POST /api/v1/account/keys/00000000-0000-4000-8000-000000000007/rotate",
                          "count": 1
                        },
                        {
                          "endpoint": "POST /api/v1/account/keys/00000000-0000-4000-8000-000000000000/rotate",
                          "count": 1
                        },
                        {
                          "endpoint": "GET /api/v1/account/keys",
                          "count": 1
                        },
                        {
                          "endpoint": "GET /api/v1/account/credits",
                          "count": 1
                        },
                        {
                          "endpoint": "GET /api/v1/account",
                          "count": 1
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No key with this id belongs to the workspace, or to the user for a personal key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no key.",
                    "value": {
                      "error": "not_found",
                      "message": "API key not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The usage could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai/enhance": {
      "post": {
        "operationId": "enhanceMessage",
        "summary": "Enhance a message",
        "description": "Rewrites a draft SMS to be clearer and more professional, in at most 160 characters, using the account's business name when it has one. With only `messageType`, writes a message of that kind. Nothing is sent and nothing is charged, and a test key gets a real rewrite too. An account may call it 10 times a minute across all of its keys. Available only to accounts with AI enhancement enabled.",
        "tags": [
          "AI message enhancement"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "enhance"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "requestBody": {
          "description": "The draft, or the kind of message to write.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnhanceMessageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- EnhancedMessage: The model rewrote the message.\n- EnhanceMessageFallback: The rewrite failed or timed out after 10 seconds, or the model is not configured. The draft comes back as it was sent, or empty when only `messageType` was.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/EnhancedMessage"
                    },
                    {
                      "$ref": "#/components/schemas/EnhanceMessageFallback"
                    }
                  ]
                },
                "examples": {
                  "fallback": {
                    "summary": "The rewrite failed, so the draft comes back unchanged with an empty explanation. Built from the handler code, not captured, since reaching it needs a paid model call that fails.",
                    "value": {
                      "enhanced": "Your order is ready for pickup",
                      "explanation": ""
                    }
                  },
                  "default": {
                    "summary": "A draft rewritten by the model. Built from the code, not captured, since every rewrite is a paid model call.",
                    "value": {
                      "enhanced": "Our weekend sale is on now! Stop by Saturday or Sunday for great deals. Reply STOP to opt out.",
                      "explanation": "Made the invitation clearer and more professional, and added opt-out wording.",
                      "model": "claude-sonnet-4-5-20250929"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: Neither `text` nor `messageType` is set, or both are empty; `text` is not a string; or `messageType` is not a string or is longer than 50 characters.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A body that is not valid JSON, answered by the body parser.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  },
                  "default": {
                    "summary": "Neither text nor messageType.",
                    "value": {
                      "error": "invalid_request",
                      "message": "text or messageType required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  },
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: AI enhancement is not enabled for the user the API key belongs to, whatever the key's workspace, or the check for it failed. Checked before `text` and `messageType`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An account without AI enhancement enabled. Built from the handler code, not captured, since the test account has it enabled.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `rate_limit_exceeded`: The key's owner has made more than 10 requests to this path in 60 seconds, counted across all of their keys.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: An unexpected error, such as a failed lookup of the business name. `message` is the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "text-not-a-string": {
                    "summary": "A text that is a number, which fails before the model is called.",
                    "value": {
                      "error": "internal_error",
                      "message": "(t || \"\").slice is not a function"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/calls": {
      "get": {
        "operationId": "listCalls",
        "summary": "List calls",
        "description": "Lists the workspace's calls, newest first: phone and browser calls, inbound and outbound, whoever handled them. A test key gets an empty page (calls are never simulated, so it has none to see), after its query is checked; a CLI session lists the workspace's calls. A call that is still live is brought up to date before it is listed.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "offset-has-more",
        "x-sendly-sdk": {
          "resource": "calls",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size, 1 to 100. Defaults to 50."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many calls to skip. Defaults to 0."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "ringing",
                "active",
                "suspended",
                "completed",
                "no_answer",
                "busy",
                "cancelled",
                "declined",
                "failed"
              ],
              "description": "Only calls with this status. Matched before a live call is brought up to date, so a listed call can carry a newer status."
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ],
              "description": "Only calls in this direction."
            },
            "required": false,
            "name": "direction",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "pstn",
                "internal"
              ],
              "description": "Only calls of this kind."
            },
            "required": false,
            "name": "kind",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only calls this agent handled."
            },
            "required": false,
            "name": "agentId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^\\+[1-9]\\d{6,14}$",
              "description": "Only calls to this E.164 number, matched exactly."
            },
            "required": false,
            "name": "to",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^\\+[1-9]\\d{6,14}$",
              "description": "Only calls from this E.164 number, matched exactly."
            },
            "required": false,
            "name": "from",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- CallList: A page of calls.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallList"
                },
                "examples": {
                  "default": {
                    "summary": "The two newest completed calls.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "object": "call",
                          "kind": "pstn",
                          "channel": "phone",
                          "direction": "inbound",
                          "status": "completed",
                          "handledBy": "agent",
                          "agentId": "00000000-0000-4000-8000-000000000002",
                          "from": "+15555550100",
                          "to": "+15555550101",
                          "callerName": "+15555550100",
                          "calleeName": "E2E receptionist",
                          "startedAt": "2026-01-01T00:00:00.000Z",
                          "answeredAt": "2026-01-01T00:00:00.000Z",
                          "endedAt": "2026-01-01T00:00:00.000Z",
                          "durationSecs": 73,
                          "creditsCharged": 22,
                          "billing": "settled",
                          "hangupClass": "agent_caller_left",
                          "recordingStatus": "ready",
                          "metadata": {}
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000003",
                          "object": "call",
                          "kind": "pstn",
                          "channel": "phone",
                          "direction": "outbound",
                          "status": "completed",
                          "handledBy": "agent",
                          "agentId": "00000000-0000-4000-8000-000000000002",
                          "from": "+15555550100",
                          "to": "+15555550101",
                          "callerName": "E2E receptionist",
                          "calleeName": "+15555550101",
                          "startedAt": "2026-01-01T00:00:00.000Z",
                          "answeredAt": "2026-01-01T00:00:00.000Z",
                          "endedAt": "2026-01-01T00:00:00.000Z",
                          "durationSecs": 72,
                          "creditsCharged": 20,
                          "billing": "settled",
                          "hangupClass": "agent_agent_hangup",
                          "recordingStatus": "ready",
                          "metadata": {
                            "sweep": "value"
                          }
                        }
                      ],
                      "pagination": {
                        "total": 5,
                        "limit": 2,
                        "offset": 0,
                        "hasMore": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: A query parameter is repeated or out of range: `limit` not an integer from 1 to 100, `offset` not an integer of at least 0, an unknown `status`, `direction` or `kind`, or a `to` or `from` that is not E.164.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A limit below 1.",
                    "value": {
                      "error": "invalid_request",
                      "message": "limit must be an integer between 1 and 100."
                    }
                  },
                  "unknown-status": {
                    "summary": "A status calls never have.",
                    "value": {
                      "error": "invalid_request",
                      "message": "status must be one of ringing, active, suspended, completed, no_answer, busy, cancelled, declined, failed."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:read` permission for calls and voice.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: The calls could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createCall",
        "summary": "Place a call",
        "description": "Rings a US or Canadian number and puts one of the workspace's AI agents on the line. The call is returned while it rings; the first minute is charged when it is answered. Needs a live key: a test key is refused, and nothing is ever simulated.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "calls",
          "method": "create"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "Who to call, and which agent talks.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCallRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- Call: The call is ringing: `status` `ringing`, `billing` `metered` (`unbilled` while charging is switched off for the platform), `creditsCharged` 0, `handledBy` `agent`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Call"
                },
                "examples": {
                  "default": {
                    "summary": "A live key placed a call: built from publicCallV1 and placeAgentPstnCall, since a test key can never place one.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "object": "call",
                      "kind": "pstn",
                      "channel": "phone",
                      "direction": "outbound",
                      "status": "ringing",
                      "handledBy": "agent",
                      "agentId": "00000000-0000-4000-8000-000000000002",
                      "from": "+15555550100",
                      "to": "+15555550101",
                      "callerName": "Front Desk",
                      "calleeName": "+15555550101",
                      "startedAt": "2026-01-01T00:00:00.000Z",
                      "answeredAt": null,
                      "endedAt": null,
                      "durationSecs": 0,
                      "creditsCharged": 0,
                      "billing": "metered",
                      "hangupClass": null,
                      "recordingStatus": null,
                      "metadata": {
                        "crmId": "lead_8812"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_request`: The body is not a JSON object, or `context` is not a string or is longer than 2,000 characters.\n- `invalid_number`: `to` is not a valid phone number with its country code, or is the `from` number itself.\n- `destination_not_supported`: `to` is outside the US and Canada, or a premium-rate number.\n- `agent_required`: `agentId` is missing or empty.\n- `invalid_metadata`: `metadata` is not an object of strings, has more than 20 keys, or a key or value is too long or a key has other characters.\n- `from_number_required`: `from` is missing and more than one of the workspace's numbers can place calls.\n- `from_number_not_supported`: The `from` number is outside the US and Canada, or is toll-free (a toll-free number receives calls but cannot place them), or `from` is missing and none of the workspace's voice-enabled numbers is a US or Canadian number that is not toll-free.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "destination_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "destination_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "destination_not_supported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "agent_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "agent_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "agent_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_metadata"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_metadata",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_metadata"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "from_number_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "from_number_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "from_number_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "from_number_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "from_number_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "from_number_not_supported"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A body that is not valid JSON, answered by the body parser.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: The balance is below one minute at the call's rate. `creditsNeeded` is the per-minute rate.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InsufficientCreditsError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:write` permission for calls and voice.\n- `live_key_required`: A test key or a CLI session called it. Calls and voice changes need a live API key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "test-key": {
                    "summary": "A test key asked to place a call, which is never simulated.",
                    "value": {
                      "error": "live_key_required",
                      "message": "Phone calls need a live API key."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `outbound_calls_not_enabled`: Calls to phone numbers are not enabled for the workspace.\n- `agent_not_found`: No agent with `agentId` is in the workspace.\n- `number_not_found`: `from` is not an active, voice-enabled number of the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "outbound_calls_not_enabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "outbound_calls_not_enabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "outbound_calls_not_enabled"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "agent_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "agent_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "agent_not_found"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `agent_disabled`: The agent is switched off.\n- `no_voice_number`: `from` is missing and none of the workspace's active numbers is voice-enabled.\n- `lines_busy`: The workspace already has as many phone calls open as it may at once, or every line of the platform is in use.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "agent_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "agent_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "agent_disabled"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_voice_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "no_voice_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_voice_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "lines_busy"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "lines_busy",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "lines_busy"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "428": {
            "description": "HTTP 428.\n\n- `e911_required`: The `from` number has no emergency address registered, or none being registered.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "e911_required"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "e911_required",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "e911_required"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `daily_call_limit`: The workspace has used today's outbound calling minutes.\n- `rate_limit_exceeded`: More than 10 calls from the key's user passed every other check within one minute. The count is kept in each server's memory, from the first such call, so it is per server.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "daily_call_limit"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "daily_call_limit",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "daily_call_limit"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rate_limit_exceeded"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "Has no `retryAfter`, unlike the per-key limit's body, and no Retry-After header.",
                      "title": "rate_limit_exceeded: calls placed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rate_limit_exceeded"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: The call could not be set up. A row already written is marked failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `voice_unavailable`, `agents_unavailable`: Outbound calling (`voice_unavailable`) or AI agents (`agents_unavailable`) are not available on the platform right now.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "voice_unavailable",
                        "agents_unavailable"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "voice_unavailable, agents_unavailable",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "voice_unavailable",
                    "agents_unavailable"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/calls/{id}": {
      "get": {
        "operationId": "getCall",
        "summary": "Get a call",
        "description": "Returns one of the workspace's calls, brought up to date first when it is still live. A call an AI agent handled carries its transcript. A test key reads no call; a CLI session reads the workspace's calls.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "calls",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The call's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- CallWithTranscript: The call.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallWithTranscript"
                },
                "examples": {
                  "default": {
                    "summary": "A completed call, an agent-handled one when there is one, with its transcript.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "object": "call",
                      "kind": "pstn",
                      "channel": "phone",
                      "direction": "inbound",
                      "status": "completed",
                      "handledBy": "agent",
                      "agentId": "00000000-0000-4000-8000-000000000002",
                      "from": "+15555550100",
                      "to": "+15555550101",
                      "callerName": "+15555550100",
                      "calleeName": "E2E receptionist",
                      "startedAt": "2026-01-01T00:00:00.000Z",
                      "answeredAt": "2026-01-01T00:00:00.000Z",
                      "endedAt": "2026-01-01T00:00:00.000Z",
                      "durationSecs": 73,
                      "creditsCharged": 22,
                      "billing": "settled",
                      "hangupClass": "agent_caller_left",
                      "recordingStatus": "ready",
                      "metadata": {},
                      "transcript": [
                        {
                          "speaker": "agent",
                          "text": "Your Sendly code is 123456",
                          "atMs": 6552
                        },
                        {
                          "speaker": "caller",
                          "text": "Your Sendly code is 123456",
                          "atMs": 21408
                        },
                        {
                          "speaker": "agent",
                          "text": "Your Sendly code is 123456",
                          "atMs": 33946
                        },
                        {
                          "speaker": "caller",
                          "text": "Your Sendly code is 123456",
                          "atMs": 48025
                        },
                        {
                          "speaker": "agent",
                          "text": "Your Sendly code is 123456",
                          "atMs": 57479
                        },
                        {
                          "speaker": "caller",
                          "text": "Your Sendly code is 123456",
                          "atMs": 64635
                        },
                        {
                          "speaker": "agent",
                          "text": "Your Sendly code is 123456",
                          "atMs": 67245
                        },
                        {
                          "speaker": "caller",
                          "text": "Your Sendly code is 123456",
                          "atMs": 67590
                        },
                        {
                          "speaker": "agent",
                          "text": "Your Sendly code is 123456",
                          "atMs": 69594
                        },
                        {
                          "speaker": "caller",
                          "text": "Your Sendly code is 123456",
                          "atMs": 72795
                        },
                        {
                          "speaker": "agent",
                          "text": "Your Sendly code is 123456",
                          "atMs": 74311
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:read` permission for calls and voice.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `call_not_found`: No call with this id is in the key's workspace, or a test key asked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "call_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "call_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "call_not_found"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no call in the workspace.",
                    "value": {
                      "error": "call_not_found",
                      "message": "No call with that id is in this workspace."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: The call could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/calls/{id}/hangup": {
      "post": {
        "operationId": "hangupCall",
        "summary": "End a call",
        "description": "Ends a call. A ringing call becomes `cancelled` with `hangupClass` `caller_cancelled`, an answered one `completed` with `normal`, and one that has already ended is returned as it is. Needs a live key. The body is ignored.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "calls",
          "method": "hangup"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The call's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Call: The call, ended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Call"
                },
                "examples": {
                  "default": {
                    "summary": "A live key ended a ringing call, which becomes cancelled: built from publicCallV1 and hangupCall, since a test key can never end one.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "object": "call",
                      "kind": "pstn",
                      "channel": "phone",
                      "direction": "outbound",
                      "status": "cancelled",
                      "handledBy": "agent",
                      "agentId": "00000000-0000-4000-8000-000000000002",
                      "from": "+15555550100",
                      "to": "+15555550101",
                      "callerName": "Front Desk",
                      "calleeName": "+15555550101",
                      "startedAt": "2026-01-01T00:00:00.000Z",
                      "answeredAt": null,
                      "endedAt": "2026-01-01T00:00:00.000Z",
                      "durationSecs": 0,
                      "creditsCharged": 0,
                      "billing": "settled",
                      "hangupClass": "caller_cancelled",
                      "recordingStatus": null,
                      "metadata": {
                        "crmId": "lead_8812"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:write` permission for calls and voice.\n- `live_key_required`: A test key or a CLI session called it. Calls and voice changes need a live API key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "test-key": {
                    "summary": "A test key asked to end a call.",
                    "value": {
                      "error": "live_key_required",
                      "message": "Phone calls need a live API key."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `call_not_found`: No call with this id is in the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "call_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "call_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "call_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: The call could not be ended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/calls/{id}/recording": {
      "get": {
        "operationId": "getCallRecording",
        "summary": "Get a call's recording",
        "description": "Says whether the call has a recording and, once it is ready, signs a download link valid for five minutes. A test key reads no call; a CLI session reads the workspace's calls.",
        "tags": [
          "Calls"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "calls",
          "method": "recording"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The call's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- CallRecording: The recording's state, with a link when it is ready.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallRecording"
                },
                "examples": {
                  "default": {
                    "summary": "A completed call with no recording ready, so no download link is signed.",
                    "value": {
                      "callId": "00000000-0000-4000-8000-000000000004",
                      "status": "none",
                      "url": null,
                      "expiresAt": null,
                      "contentType": null
                    }
                  },
                  "ready": {
                    "summary": "A recording that is ready, with its signed link: built from recordingFor, since signed links are never stored in a fixture.",
                    "value": {
                      "callId": "00000000-0000-4000-8000-000000000001",
                      "status": "ready",
                      "url": "https://recordings.example.com/00000000-0000-4000-8000-000000000001.ogg?X-Amz-Expires=300&X-Amz-Signature=placeholder",
                      "expiresAt": "2026-01-01T00:00:00.000Z",
                      "contentType": "audio/ogg"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:read` permission for calls and voice.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `call_not_found`: No call with this id is in the key's workspace, or a test key asked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "call_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "call_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "call_not_found"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no call in the workspace.",
                    "value": {
                      "error": "call_not_found",
                      "message": "No call with that id is in this workspace."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: The call could not be read, or the download link could not be signed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/campaigns": {
      "get": {
        "operationId": "listCampaigns",
        "summary": "List campaigns",
        "description": "Lists the workspace's campaigns, newest first, with each sent campaign's message counts and credits read from its batch.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "top-level-offset",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "list"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "Page size. Defaults to 50, which is also what 0 or a value that is not a number gives. A value below 1 is raised to 1. There is no maximum."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many campaigns to skip. Ignored when `page` is set."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "The page to return, starting at 1. Takes precedence over `offset`."
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only campaigns with this status. `sent` matches `completed` campaigns."
            },
            "required": false,
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- CampaignList: A page of campaigns.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignList"
                },
                "examples": {
                  "default": {
                    "summary": "The two newest campaigns.",
                    "value": {
                      "campaigns": [
                        {
                          "id": "camp_placeholder2",
                          "userId": "00000000-0000-4000-8000-000000000001",
                          "organizationId": null,
                          "name": "Contract capture manual",
                          "status": "draft",
                          "messageText": "Hi {{name}}, doors open at 9",
                          "fromSender": null,
                          "targetType": "manual",
                          "targetListId": null,
                          "manualRecipients": [
                            {
                              "name": "Avery",
                              "phone": "+15555550100"
                            }
                          ],
                          "excludeOptedOut": true,
                          "sendNow": false,
                          "scheduledAt": null,
                          "timezone": "America/New_York",
                          "batchId": null,
                          "totalRecipients": 0,
                          "estimatedCredits": 0,
                          "sentCount": 0,
                          "deliveredCount": 0,
                          "failedCount": 0,
                          "creditsUsed": 0,
                          "creditsRefunded": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z",
                          "sentAt": null,
                          "completedAt": null,
                          "text": "Your Sendly code is 123456",
                          "contact_list_ids": [],
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "camp_placeholder1",
                          "userId": "00000000-0000-4000-8000-000000000001",
                          "organizationId": null,
                          "name": "Contract capture draft",
                          "status": "draft",
                          "messageText": "Hi {{name}}, doors open at 9",
                          "fromSender": null,
                          "targetType": "contact_list",
                          "targetListId": null,
                          "manualRecipients": null,
                          "excludeOptedOut": true,
                          "sendNow": false,
                          "scheduledAt": null,
                          "timezone": "America/New_York",
                          "batchId": null,
                          "totalRecipients": 0,
                          "estimatedCredits": 0,
                          "sentCount": 0,
                          "deliveredCount": 0,
                          "failedCount": 0,
                          "creditsUsed": 0,
                          "creditsRefunded": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z",
                          "sentAt": null,
                          "completedAt": null,
                          "text": "Your Sendly code is 123456",
                          "contact_list_ids": [],
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        }
                      ],
                      "total": 2,
                      "limit": 2,
                      "offset": 0
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `fetch_failed`: The campaigns could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "fetch_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "fetch_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "fetch_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createCampaign",
        "summary": "Create a campaign",
        "description": "Creates a draft SMS campaign. Nothing is sent until `POST /api/v1/campaigns/{id}/send` or a schedule.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "create"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The campaign to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCampaignRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- Campaign: The campaign was created as a draft.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "examples": {
                  "default": {
                    "summary": "A draft campaign with no contact list yet.",
                    "value": {
                      "id": "camp_placeholder1",
                      "userId": "00000000-0000-4000-8000-000000000001",
                      "organizationId": null,
                      "name": "Contract capture draft",
                      "status": "draft",
                      "messageText": "Hi {{name}}, doors open at 9",
                      "fromSender": null,
                      "targetType": "contact_list",
                      "targetListId": null,
                      "manualRecipients": null,
                      "excludeOptedOut": true,
                      "sendNow": false,
                      "scheduledAt": null,
                      "timezone": "America/New_York",
                      "batchId": null,
                      "totalRecipients": 0,
                      "estimatedCredits": 0,
                      "sentCount": 0,
                      "deliveredCount": 0,
                      "failedCount": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "sentAt": null,
                      "completedAt": null,
                      "text": "Your Sendly code is 123456",
                      "contact_list_ids": [],
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "manual": {
                    "summary": "A draft campaign to one number given in the body.",
                    "value": {
                      "id": "camp_placeholder2",
                      "userId": "00000000-0000-4000-8000-000000000001",
                      "organizationId": null,
                      "name": "Contract capture manual",
                      "status": "draft",
                      "messageText": "Hi {{name}}, doors open at 9",
                      "fromSender": null,
                      "targetType": "manual",
                      "targetListId": null,
                      "manualRecipients": [
                        {
                          "name": "Avery",
                          "phone": "+15555550100"
                        }
                      ],
                      "excludeOptedOut": true,
                      "sendNow": false,
                      "scheduledAt": null,
                      "timezone": "America/New_York",
                      "batchId": null,
                      "totalRecipients": 0,
                      "estimatedCredits": 0,
                      "sentCount": 0,
                      "deliveredCount": 0,
                      "failedCount": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "sentAt": null,
                      "completedAt": null,
                      "text": "Your Sendly code is 123456",
                      "contact_list_ids": [],
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `channel_not_supported`: `channel`, or the `channel` of an entry in `messages`, is set and is not `sms`.\n- `invalid_request`: `name` or the message is missing, more than one contact list was sent, the contact list or template is not this workspace's, or the template uses a placeholder a campaign cannot fill.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "channel_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "channel_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "channel_not_supported"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No text, messageText or templateId.",
                    "value": {
                      "error": "invalid_request",
                      "message": "name and text (or messageText or templateId) are required"
                    }
                  },
                  "list-not-found": {
                    "summary": "A contact list that is not the workspace's.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Contact list not found"
                    }
                  },
                  "two-lists": {
                    "summary": "Two contact lists in contactListIds.",
                    "value": {
                      "error": "invalid_request",
                      "message": "A campaign targets one contact list; pass a single ID in contactListIds"
                    }
                  },
                  "whatsapp-channel": {
                    "summary": "A campaign asked for the WhatsApp channel.",
                    "value": {
                      "error": "channel_not_supported",
                      "message": "Campaigns are SMS/MMS only. Send WhatsApp messages via POST /v1/messages with channel \"whatsapp\"."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `live_key_required`: A test key sent `status: \"scheduled\"`. Checked before the body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `list_lookup_failed`, `template_lookup_failed`: The contact list or the template could not be read.\n- `create_failed`: The campaign could not be stored, such as a name over 255 characters. `message` holds the database's error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "list_lookup_failed",
                            "template_lookup_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "list_lookup_failed, template_lookup_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "list_lookup_failed",
                        "template_lookup_failed"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "create_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "create_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "create_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/campaigns/{id}": {
      "get": {
        "operationId": "getCampaign",
        "summary": "Get a campaign",
        "description": "Returns one campaign of the workspace. A sent campaign's counts and credits are read from its batch.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Campaign: The campaign.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "examples": {
                  "default": {
                    "summary": "A draft campaign.",
                    "value": {
                      "id": "camp_placeholder1",
                      "userId": "00000000-0000-4000-8000-000000000001",
                      "organizationId": null,
                      "name": "Contract capture draft",
                      "status": "draft",
                      "messageText": "Hi {{name}}, doors open at 9",
                      "fromSender": null,
                      "targetType": "contact_list",
                      "targetListId": null,
                      "manualRecipients": null,
                      "excludeOptedOut": true,
                      "sendNow": false,
                      "scheduledAt": null,
                      "timezone": "America/New_York",
                      "batchId": null,
                      "totalRecipients": 0,
                      "estimatedCredits": 0,
                      "sentCount": 0,
                      "deliveredCount": 0,
                      "failedCount": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "sentAt": null,
                      "completedAt": null,
                      "text": "Your Sendly code is 123456",
                      "contact_list_ids": [],
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No campaign with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no campaign.",
                    "value": {
                      "error": "not_found",
                      "message": "Campaign not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateCampaign",
        "summary": "Update a campaign",
        "description": "Changes a draft or scheduled campaign. A test key cannot change a scheduled campaign, which is sent for real: it can cancel it instead.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "update"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCampaignRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- Campaign: The updated campaign.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "examples": {
                  "default": {
                    "summary": "A draft renamed.",
                    "value": {
                      "id": "camp_placeholder1",
                      "userId": "00000000-0000-4000-8000-000000000001",
                      "organizationId": null,
                      "name": "Contract capture draft, renamed",
                      "status": "draft",
                      "messageText": "Hi {{name}}, doors open at 9",
                      "fromSender": null,
                      "targetType": "contact_list",
                      "targetListId": null,
                      "manualRecipients": null,
                      "excludeOptedOut": true,
                      "sendNow": false,
                      "scheduledAt": null,
                      "timezone": "America/New_York",
                      "batchId": null,
                      "totalRecipients": 0,
                      "estimatedCredits": 0,
                      "sentCount": 0,
                      "deliveredCount": 0,
                      "failedCount": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "sentAt": null,
                      "completedAt": null,
                      "text": "Your Sendly code is 123456",
                      "contact_list_ids": [],
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `cannot_edit`: The campaign is not a draft or scheduled.\n- `invalid_request`: More than one contact list was sent, the contact list or template is not this workspace's, or the template uses a placeholder a campaign cannot fill.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "cannot_edit"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "cannot_edit",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "cannot_edit"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A campaign that was already sent.",
                    "value": {
                      "error": "cannot_edit",
                      "message": "Only draft or scheduled campaigns can be edited"
                    }
                  },
                  "two-lists": {
                    "summary": "Two contact lists in contactListIds.",
                    "value": {
                      "error": "invalid_request",
                      "message": "A campaign targets one contact list; pass a single ID in contactListIds"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `live_key_required`: A test key sent `status: \"scheduled\"` (checked first), or asked to change a campaign that is scheduled.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No campaign with this id belongs to the key's workspace.\n- `update_failed`: The campaign was deleted while it was being updated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "update_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "update_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "update_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no campaign.",
                    "value": {
                      "error": "not_found",
                      "message": "Campaign not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `list_lookup_failed`, `template_lookup_failed`: The contact list or the template could not be read.\n- `update_failed`: The change could not be stored, such as a `scheduledAt` sent here or a name over 255 characters. `message` holds the database's error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "list_lookup_failed",
                            "template_lookup_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "list_lookup_failed, template_lookup_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "list_lookup_failed",
                        "template_lookup_failed"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "update_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "update_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "update_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteCampaign",
        "summary": "Delete a campaign",
        "description": "Deletes a campaign that is not sending. Messages it sent are kept.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "delete"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.\n\n- The campaign was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `cannot_delete`: The campaign is sending.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "cannot_delete"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "cannot_delete",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "cannot_delete"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No campaign with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no campaign.",
                    "value": {
                      "error": "not_found",
                      "message": "Campaign not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `delete_failed`: The campaign could not be deleted. `message` holds the database's error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "delete_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "delete_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "delete_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/campaigns/{id}/cancel": {
      "post": {
        "operationId": "cancelCampaign",
        "summary": "Cancel a scheduled campaign",
        "description": "Cancels a scheduled campaign. A cancelled campaign cannot be scheduled or sent again.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "cancel"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Campaign: The campaign, now `cancelled`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "examples": {
                  "default": {
                    "summary": "A scheduled campaign cancelled.",
                    "value": {
                      "id": "camp_placeholder1",
                      "userId": "00000000-0000-4000-8000-000000000001",
                      "organizationId": null,
                      "name": "Contract capture draft, renamed",
                      "status": "cancelled",
                      "messageText": "Hi {{name}}, doors open at 9",
                      "fromSender": null,
                      "targetType": "contact_list",
                      "targetListId": null,
                      "manualRecipients": null,
                      "excludeOptedOut": true,
                      "sendNow": false,
                      "scheduledAt": "2026-01-01T00:00:00.000Z",
                      "timezone": "America/Los_Angeles",
                      "batchId": null,
                      "totalRecipients": 0,
                      "estimatedCredits": 0,
                      "sentCount": 0,
                      "deliveredCount": 0,
                      "failedCount": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "sentAt": null,
                      "completedAt": null,
                      "text": "Your Sendly code is 123456",
                      "contact_list_ids": [],
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_status`: The campaign is not scheduled.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_status"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_status",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_status"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A campaign that is not scheduled.",
                    "value": {
                      "error": "invalid_status",
                      "message": "Only scheduled campaigns can be cancelled"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No campaign with this id belongs to the key's workspace.\n- `cancel_failed`: The campaign was deleted while it was being cancelled.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "cancel_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "cancel_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "cancel_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no campaign.",
                    "value": {
                      "error": "not_found",
                      "message": "Campaign not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `cancel_failed`: The campaign could not be updated. `message` holds the database's error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "cancel_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "cancel_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "cancel_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/campaigns/{id}/clone": {
      "post": {
        "operationId": "cloneCampaign",
        "summary": "Clone a campaign",
        "description": "Copies a campaign of any status into a new draft with the same message, sender, recipients and timezone.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "clone"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "Optional: the copy's name.",
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloneCampaignRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- Campaign: The copy, as a draft.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "examples": {
                  "default": {
                    "summary": "A copy of a draft, with a new name.",
                    "value": {
                      "id": "camp_placeholder3",
                      "userId": "00000000-0000-4000-8000-000000000001",
                      "organizationId": null,
                      "name": "Contract capture copy",
                      "status": "draft",
                      "messageText": "Hi {{name}}, doors open at 9",
                      "fromSender": null,
                      "targetType": "contact_list",
                      "targetListId": null,
                      "manualRecipients": null,
                      "excludeOptedOut": true,
                      "sendNow": false,
                      "scheduledAt": null,
                      "timezone": "America/New_York",
                      "batchId": null,
                      "totalRecipients": 0,
                      "estimatedCredits": 0,
                      "sentCount": 0,
                      "deliveredCount": 0,
                      "failedCount": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "sentAt": null,
                      "completedAt": null,
                      "text": "Your Sendly code is 123456",
                      "contact_list_ids": [],
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `name` is longer than 255 characters, or the original's contact list is no longer this workspace's.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A name longer than 255 characters.",
                    "value": {
                      "error": "invalid_request",
                      "message": "name must be 255 characters or fewer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No campaign with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no campaign.",
                    "value": {
                      "error": "not_found",
                      "message": "Campaign not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `list_lookup_failed`: The original's contact list could not be read.\n- `create_failed`: The copy could not be stored. `message` holds the database's error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "list_lookup_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "list_lookup_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "list_lookup_failed"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "create_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "create_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "create_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/campaigns/{id}/preview": {
      "get": {
        "operationId": "previewCampaign",
        "summary": "Preview a campaign",
        "description": "Counts the campaign's recipients as they are now and estimates what sending would cost, per destination country.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "preview"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- CampaignPreview: The recipients and the estimate.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignPreview"
                },
                "examples": {
                  "default": {
                    "summary": "A campaign to one number, previewed with a test key.",
                    "value": {
                      "totalRecipients": 1,
                      "estimatedCredits": 2,
                      "optedOutCount": 0,
                      "invalidCount": 0,
                      "invalidNumberCount": 0,
                      "landlineCount": 0,
                      "sampleRecipients": [
                        {
                          "phone": "+15555550100",
                          "name": "Avery"
                        }
                      ],
                      "blockedCount": 0,
                      "sendableCount": 1,
                      "byCountry": {
                        "US": {
                          "count": 1,
                          "credits": 2,
                          "allowed": true
                        }
                      },
                      "warnings": [],
                      "messagingProfile": {
                        "canSendDomestic": true,
                        "canSendInternational": true,
                        "verificationType": "both",
                        "verificationStatus": "verified"
                      },
                      "recipientCount": 1,
                      "currentBalance": 170,
                      "hasEnoughCredits": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No campaign with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no campaign.",
                    "value": {
                      "error": "not_found",
                      "message": "Campaign not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/campaigns/{id}/schedule": {
      "post": {
        "operationId": "scheduleCampaign",
        "summary": "Schedule a campaign",
        "description": "Schedules a draft campaign to send at `scheduledAt`, once the balance covers its estimate. The scheduled send runs as a live send, so it needs a live key.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "schedule"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "When to send.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleCampaignRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- Campaign: The campaign, now `scheduled`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "examples": {
                  "default": {
                    "summary": "A draft with no recipients, scheduled two years ahead, past the delayed-event window, and cancelled straight after.",
                    "value": {
                      "id": "camp_placeholder1",
                      "userId": "00000000-0000-4000-8000-000000000001",
                      "organizationId": null,
                      "name": "Contract capture draft, renamed",
                      "status": "scheduled",
                      "messageText": "Hi {{name}}, doors open at 9",
                      "fromSender": null,
                      "targetType": "contact_list",
                      "targetListId": null,
                      "manualRecipients": null,
                      "excludeOptedOut": true,
                      "sendNow": false,
                      "scheduledAt": "2026-01-01T00:00:00.000Z",
                      "timezone": "America/Los_Angeles",
                      "batchId": null,
                      "totalRecipients": 0,
                      "estimatedCredits": 0,
                      "sentCount": 0,
                      "deliveredCount": 0,
                      "failedCount": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "sentAt": null,
                      "completedAt": null,
                      "text": "Your Sendly code is 123456",
                      "contact_list_ids": [],
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `scheduledAt` is missing or is not a date.\n- `invalid_status`: The campaign is not a draft.\n- `invalid_schedule`: `scheduledAt` is not in the future.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_status"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_status",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_status"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_schedule"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_schedule",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_schedule"
                      ]
                    }
                  ]
                },
                "examples": {
                  "in-the-past": {
                    "summary": "A scheduledAt in the past.",
                    "value": {
                      "error": "invalid_schedule",
                      "message": "Scheduled time must be in the future"
                    }
                  },
                  "invalid-date": {
                    "summary": "A scheduledAt that is not a date.",
                    "value": {
                      "error": "invalid_request",
                      "message": "scheduledAt must be a valid ISO date string"
                    }
                  },
                  "default": {
                    "summary": "No scheduledAt.",
                    "value": {
                      "error": "invalid_request",
                      "message": "scheduledAt is required"
                    }
                  },
                  "not-draft": {
                    "summary": "A campaign that is already scheduled.",
                    "value": {
                      "error": "invalid_status",
                      "message": "Cannot schedule a campaign with status \"scheduled\""
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: The balance does not cover the campaign's estimate.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "insufficient_credits"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "needed": {
                      "type": "integer",
                      "description": "The credits the campaign is estimated to cost."
                    },
                    "available": {
                      "type": "integer",
                      "description": "The balance."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "needed",
                    "available"
                  ],
                  "title": "insufficient_credits, at scheduling",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "insufficient_credits"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `live_key_required`: A test key called it, whatever the campaign. Checked after `scheduledAt` is read and before the campaign is looked up.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No campaign with this id belongs to the key's workspace.\n- `schedule_failed`: The campaign was deleted while it was being scheduled.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "schedule_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "schedule_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "schedule_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no campaign.",
                    "value": {
                      "error": "not_found",
                      "message": "Campaign not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `schedule_failed`: The schedule could not be stored, such as for a `timezone` of `null`. `message` holds the database's error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "schedule_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "schedule_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "schedule_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/campaigns/{id}/send": {
      "post": {
        "operationId": "sendCampaign",
        "summary": "Send a campaign",
        "description": "Sends a draft or scheduled campaign now, as marketing messages, to every recipient who has not opted out and can receive texts. A test key simulates every message and charges nothing. A send that is refused after the campaign was claimed leaves it `failed`, and one with no recipients leaves it `completed`; neither can be sent again.",
        "tags": [
          "Campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "campaigns:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "campaigns",
          "method": "send"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "Optional: the number to send from.",
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendCampaignRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- Campaign sent: The campaign was sent, or simulated.\n- Campaign queued: The campaign's batch was queued, to be sent in the background.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/CampaignSendResult"
                    },
                    {
                      "$ref": "#/components/schemas/CampaignSendQueued"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A campaign to one number, sent with a test key and simulated.",
                    "value": {
                      "batchId": "batch_placeholder4",
                      "status": "processing",
                      "total": 1,
                      "sent": 0,
                      "failed": 0,
                      "optedOutSkipped": 0,
                      "invalidSkipped": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "messages": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_from_number`: `from` is not an active number of this workspace that can send campaigns, or it could not be checked.\n- `invalid_status`: The campaign is not a draft or scheduled.\n- `no_recipients`: The campaign has no recipient who can be sent to. It is now `completed`.\n- `all_opted_out`: Every recipient opted out. The campaign is now `failed`.\n- `all_recipients_blocked`: Every recipient opted out or cannot receive texts. The campaign is now `failed`.\n- `compliance_blocked`: The text has restricted (SHAFT) content. The campaign is now `failed`.\n- `invalid_request`: A recipient's message is empty once its placeholders are filled. The campaign is now `failed`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_from_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_from_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_from_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_status"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_status",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_status"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_recipients"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "no_recipients",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_recipients"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "all_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "optedOutCount": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "optedOutCount"
                      ],
                      "title": "all_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "all_opted_out"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "all_recipients_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "optedOutCount": {
                          "type": "integer"
                        },
                        "invalidCount": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "optedOutCount",
                        "invalidCount"
                      ],
                      "title": "all_recipients_blocked",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "all_recipients_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SHAFT_CONTENT_DETECTED"
                          ]
                        },
                        "category": {
                          "type": "string",
                          "description": "The restricted category the text matched. Known values: `sex`, `hate`, `alcohol`, `firearms`, `tobacco`, `cannabis`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "sex",
                            "hate",
                            "alcohol",
                            "firearms",
                            "tobacco",
                            "cannabis"
                          ]
                        },
                        "matchedTerms": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "category",
                        "matchedTerms",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: SHAFT content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-from": {
                    "summary": "A from number the workspace does not have.",
                    "value": {
                      "error": "invalid_from_number",
                      "message": "Phone number +15555550100 is not available in this workspace. Use one of your verified or ported numbers."
                    }
                  },
                  "default": {
                    "summary": "A campaign that was already sent.",
                    "value": {
                      "error": "invalid_status",
                      "message": "Cannot send a campaign with status \"completed\""
                    }
                  },
                  "no-recipients": {
                    "summary": "A campaign with no recipients, which is left completed.",
                    "value": {
                      "error": "no_recipients",
                      "message": "No valid recipients found for this campaign"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: The balance does not cover the send. The campaign is now `failed`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "insufficient_credits"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "creditsNeeded": {
                      "type": "integer"
                    },
                    "currentBalance": {
                      "type": "integer"
                    },
                    "messageCount": {
                      "type": "integer",
                      "description": "How many recipients the send had."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "creditsNeeded",
                    "currentBalance",
                    "messageCount"
                  ],
                  "title": "insufficient_credits, for a batch",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "insufficient_credits"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (campaigns:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `workspace_suspended`: The workspace is suspended. The campaign is now `failed`.\n- `account_under_review`: A live key on a new account sent text that reads like a payment scam. A workspace's campaign also suspends the workspace.\n- `not_verified`: A live key on an account with no completed business verification.\n- `access_denied`: The account's verification does not cover a recipient's destination.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "account_under_review"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "account_under_review",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "account_under_review"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "not_verified"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "not_verified",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "not_verified"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "access_denied"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "access_denied",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "access_denied"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No campaign with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no campaign.",
                    "value": {
                      "error": "not_found",
                      "message": "Campaign not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `already_claimed`: Another request or the scheduler started sending the campaign first.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "already_claimed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "already_claimed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "already_claimed"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `quota_exceeded`: The send would pass the workspace's monthly message quota. The campaign is now `failed`.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "quota_exceeded"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "quota": {
                          "type": "integer",
                          "description": "The workspace's monthly message quota."
                        },
                        "used": {
                          "type": "integer",
                          "description": "Messages sent this month."
                        },
                        "batchSize": {
                          "type": "integer",
                          "description": "How many messages the send would add."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "quota",
                        "used",
                        "batchSize"
                      ],
                      "title": "quota_exceeded, for a batch",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "quota_exceeded"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `send_failed`: The send failed unexpectedly. The campaign is now `failed`. `message` holds the error's text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "send_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "send_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "send_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists": {
      "get": {
        "operationId": "listContactLists",
        "summary": "List contact lists",
        "description": "Lists every contact list of the workspace, newest first, with no paging.",
        "tags": [
          "Contact lists"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts.lists",
          "method": "list"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactLists: Every list of the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactLists"
                },
                "examples": {
                  "default": {
                    "summary": "The workspace's lists: the one the capture created.",
                    "value": {
                      "lists": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "name": "Contract capture list, renamed",
                          "description": null,
                          "contact_count": 2,
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The lists could not be read. `message` is the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createContactList",
        "summary": "Create a contact list",
        "description": "Creates an empty contact list in the workspace.",
        "tags": [
          "Contact lists"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts.lists",
          "method": "create"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The list to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContactListRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- ContactListCreated: The list was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListCreated"
                },
                "examples": {
                  "default": {
                    "summary": "A new list with a description.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "name": "Contract capture list",
                      "description": "Customers who asked for updates",
                      "contact_count": 0,
                      "created_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `validation_error`: `name` is missing, is not a string, or is blank.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string",
                          "enum": [
                            "name is required"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error: name is required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A blank name.",
                    "value": {
                      "error": "validation_error",
                      "message": "name is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The list could not be created. `message` is the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/{id}": {
      "get": {
        "operationId": "getContactList",
        "summary": "Get a contact list",
        "description": "Returns one contact list of the workspace with one page of its members.",
        "tags": [
          "Contact lists"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-paged-by": [
          "limit",
          "offset"
        ],
        "x-sendly-sdk": {
          "resource": "contacts.lists",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The list's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many members to return, up to 100. Defaults to 50, which is also what 0 or a value that is not a number gives. A value above 100 is lowered to 100."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many members to skip, newest added first. Defaults to 0."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactListDetail: The list and one page of its members.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListDetail"
                },
                "examples": {
                  "default": {
                    "summary": "The list the capture created, after the same contact was added to it twice: both memberships are counted, and the contact appears once.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "name": "Contract capture list",
                      "description": "Customers who asked for updates",
                      "contact_count": 2,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z",
                      "contacts": [
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "phone_number": "+15555550100",
                          "name": "Contract capture contact",
                          "email": null
                        }
                      ],
                      "contacts_total": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No list with this id belongs to the key's workspace. `message` is `Contact list not found`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no list.",
                    "value": {
                      "error": "not_found",
                      "message": "Contact list not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The list could not be read, including when `limit` or `offset` is negative, which the database refuses, and when the list was deleted while it was being read (`message` is `Contact list not found`). Otherwise `message` is the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateContactList",
        "summary": "Update a contact list",
        "description": "Renames a contact list or changes its description.",
        "tags": [
          "Contact lists"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts.lists",
          "method": "update"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The list's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateContactListRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactList: The list, as updated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactList"
                },
                "examples": {
                  "default": {
                    "summary": "A new name, with the description cleared.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "name": "Contract capture list, renamed",
                      "description": null,
                      "contact_count": 2,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `validation_error`: `name` is not a string, or is blank. Checked only after the list is found.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string",
                          "enum": [
                            "name must be a non-empty string"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error: name must be a non-empty string",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A name that is not a string.",
                    "value": {
                      "error": "validation_error",
                      "message": "name must be a non-empty string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No list with this id belongs to the key's workspace, or it was deleted before the update. `message` is `Contact list not found`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no list.",
                    "value": {
                      "error": "not_found",
                      "message": "Contact list not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The list could not be updated. `message` is the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteContactList",
        "summary": "Delete a contact list",
        "description": "Deletes a contact list. The contacts in it are kept.",
        "tags": [
          "Contact lists"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts.lists",
          "method": "delete"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The list's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.\n\n- The list was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No list with this id belongs to the key's workspace. `message` is `Contact list not found`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "The list just deleted.",
                    "value": {
                      "error": "not_found",
                      "message": "Contact list not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The list could not be deleted. `message` is the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/{id}/contacts": {
      "post": {
        "operationId": "addContactsToList",
        "summary": "Add contacts to a list",
        "description": "Adds contacts of the workspace to a list, and recounts its `contact_count`. A contact already in the list is added again, as a second membership.",
        "tags": [
          "Contact lists"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts.lists",
          "method": "addContacts"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The list's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The contacts to add.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddContactsToListRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactsAddedToList: At least one id matched a contact of this workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactsAddedToList"
                },
                "examples": {
                  "already-member": {
                    "summary": "The same contact again, which is added a second time and counted.",
                    "value": {
                      "success": true,
                      "added_count": 1
                    }
                  },
                  "default": {
                    "summary": "A contact of the workspace and an id that matches none.",
                    "value": {
                      "success": true,
                      "added_count": 1
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `validation_error`: `contact_ids` is missing, is not an array, or is empty. Checked before the list is looked up.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string",
                          "enum": [
                            "contact_ids array is required"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error: contact_ids array is required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An empty contact_ids array.",
                    "value": {
                      "error": "validation_error",
                      "message": "contact_ids array is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: `message` is `Contact list not found` when no list with this id belongs to the key's workspace, and `No valid contacts found` when no id matches a contact of this workspace. Otherwise the contacts could not be added, and `message` is the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no contact of the workspace.",
                    "value": {
                      "error": "internal_error",
                      "message": "No valid contacts found"
                    }
                  },
                  "missing-list": {
                    "summary": "A list id that matches no list.",
                    "value": {
                      "error": "internal_error",
                      "message": "Contact list not found"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/{id}/contacts/{contactId}": {
      "delete": {
        "operationId": "removeContactFromList",
        "summary": "Remove a contact from a list",
        "description": "Takes a contact out of a list, and recounts its `contact_count`. The contact itself is kept.",
        "tags": [
          "Contact lists"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts.lists",
          "method": "removeContact"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The list's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The contact's id."
            },
            "required": true,
            "name": "contactId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactRemovedFromList: The contact is not in the list now, including when it never was or no such contact exists. Every membership of the contact in the list is removed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactRemovedFromList"
                },
                "examples": {
                  "default": {
                    "summary": "A contact in the list, with both of its memberships.",
                    "value": {
                      "success": true
                    }
                  },
                  "not-member": {
                    "summary": "A contact id that is not in the list, which still succeeds.",
                    "value": {
                      "success": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: `message` is `Contact list not found` when no list with this id belongs to the key's workspace. Otherwise the contact could not be removed, and `message` is the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A list id that matches no list.",
                    "value": {
                      "error": "internal_error",
                      "message": "Contact list not found"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacts": {
      "get": {
        "operationId": "listContacts",
        "summary": "List contacts",
        "description": "Lists the workspace's contacts, newest first. A key without a workspace lists its owner's contacts that have no workspace.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "top-level-offset",
        "x-sendly-sdk": {
          "resource": "contacts",
          "method": "list"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size, up to 100. Defaults to 50, which is also what 0 or a value that is not a number gives. A value above 100 is lowered to 100. A negative value removes the page limit, so every matching contact is returned, and `limit` echoes it."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many contacts to skip. Defaults to 0."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only contacts whose name, phone number or email contains this text, matching case."
            },
            "required": false,
            "name": "search",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only members of this contact list."
            },
            "required": false,
            "name": "list_id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactListResponse: A page of contacts.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListResponse"
                },
                "examples": {
                  "default": {
                    "summary": "Contacts matching the test number.",
                    "value": {
                      "contacts": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "phone_number": "+15555550100",
                          "name": "Ada Lovelace",
                          "email": null,
                          "metadata": {
                            "tier": "value"
                          },
                          "opted_out": false,
                          "line_type": null,
                          "carrier_name": null,
                          "line_type_checked_at": null,
                          "invalid_reason": null,
                          "invalidated_at": null,
                          "user_marked_valid_at": null,
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        }
                      ],
                      "total": 1,
                      "limit": 5,
                      "offset": 0
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The contacts could not be read, as when `offset` is negative. `message` is the database's own error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "negative-offset": {
                    "summary": "A negative offset, which reaches the database as is.",
                    "value": {
                      "error": "internal_error",
                      "message": "OFFSET must not be negative"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createContact",
        "summary": "Create a contact",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts",
          "method": "create"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The contact to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone_number": {
                    "type": "string",
                    "pattern": "^\\+[1-9]\\d{6,14}$",
                    "description": "The phone number, in E.164 format. The server also takes one with spaces, dashes and parentheses, which it removes before checking."
                  },
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": {},
                    "description": "Your own JSON object, stored with the contact."
                  }
                },
                "required": [
                  "phone_number"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- ContactCreated: The contact was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactCreated"
                },
                "examples": {
                  "default": {
                    "summary": "A new contact with a name and metadata.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "phone_number": "+15555550100",
                      "name": "Ada Lovelace",
                      "email": null,
                      "metadata": {
                        "tier": "gold"
                      },
                      "created_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `validation_error`: `phone_number` is missing, or is not in E.164 format once spaces, dashes and parentheses are removed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-phone": {
                    "summary": "A phone number that is not in E.164 format.",
                    "value": {
                      "error": "validation_error",
                      "message": "Invalid phone format. Must be E.164 format (e.g., +15555550101)"
                    }
                  },
                  "default": {
                    "summary": "No phone_number.",
                    "value": {
                      "error": "validation_error",
                      "message": "phone_number is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `conflict`: The workspace already has a contact with this phone number.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "conflict"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "existing_id": {
                      "type": "string",
                      "description": "The contact that already has this phone number."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "existing_id"
                  ],
                  "title": "conflict: phone number taken",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "conflict"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The same phone number again.",
                    "value": {
                      "error": "conflict",
                      "message": "Contact with this phone number already exists",
                      "existing_id": "00000000-0000-4000-8000-000000000001"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The contact could not be created, as when `phone_number` is not a string. `message` is the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "numeric-phone": {
                    "summary": "A phone_number sent as a JSON number.",
                    "value": {
                      "error": "internal_error",
                      "message": "l.replace is not a function"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacts/bulk-mark-valid": {
      "post": {
        "operationId": "bulkMarkContactsValid",
        "summary": "Mark many contacts valid",
        "description": "Clears the invalid flag and sets `userMarkedValidAt` on every contact named, flagged or not, so a failed send or a lookup never flags them again. Ids of other workspaces are skipped. A key without a workspace acts on the workspace `X-Organization-Id` names or else its owner's personal workspace, so the contacts it created through `POST /api/v1/contacts` are skipped too. Sends one `contacts.bulk_marked_valid` event when any contact changed.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts",
          "method": "bulkMarkValid"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "Exactly one of `ids` or `listId`.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "ids": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "maxItems": 10000,
                        "description": "Up to 10,000 contact ids. An empty array clears nothing."
                      }
                    },
                    "required": [
                      "ids"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "listId": {
                        "type": "string",
                        "description": "Every member of this contact list, in place of `ids`."
                      }
                    },
                    "required": [
                      "listId"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- BulkMarkValidResult: The contacts were updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkMarkValidResult"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no contact, so nothing is cleared.",
                    "value": {
                      "cleared": 0
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- Bulk mark-valid refused: Neither or both of `ids` and `listId`, `ids` not an array of strings or longer than 10,000, or `listId` not a string.\n- Insufficient permissions: requires contacts:write: The caller's workspace role lacks `contacts:write`.\n- Contacts request failed: The caller's workspace role lacks `contacts:write`, or the update failed.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Provide either 'ids' (string[]) or 'listId'",
                            "Provide only one of 'ids' or 'listId'",
                            "ids must be string[]",
                            "ids array capped at 10,000 per request",
                            "listId must be a string"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Bulk mark-valid refused",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Insufficient permissions: requires contacts:write"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "forbidden"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Insufficient permissions: requires contacts:write",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "forbidden"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "forbidden"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds the error's own text, and there is no `message`. In a team workspace whose role lacks `contacts:write` it is `Insufficient permissions: requires contacts:write`, the only text that carries a code here.",
                      "title": "Contacts request failed",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "forbidden"
                      ]
                    }
                  ]
                },
                "examples": {
                  "both": {
                    "summary": "Both ids and listId.",
                    "value": {
                      "error": "Provide only one of 'ids' or 'listId'"
                    }
                  },
                  "ids-not-strings": {
                    "summary": "ids holding a number.",
                    "value": {
                      "error": "ids must be string[]"
                    }
                  },
                  "default": {
                    "summary": "Neither ids nor listId.",
                    "value": {
                      "error": "Provide either 'ids' (string[]) or 'listId'"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (contacts:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacts/import": {
      "post": {
        "operationId": "importContacts",
        "summary": "Import contacts",
        "description": "Creates up to 10,000 contacts in one request. A row whose number the workspace already has is skipped and counted in `skippedDuplicates`. With `listId`, the new contacts and the existing ones named are added to that list.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts",
          "method": "import"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The contacts to import.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contacts": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "phone": {
                          "type": "string",
                          "pattern": "^\\+[1-9]\\d{6,14}$",
                          "description": "The phone number, in E.164 format. The server reads `phoneNumber`, then `to`, when `phone` is absent or empty, but a row without `phone` is not described here. The server also takes one with spaces, dashes and parentheses, which it removes before checking."
                        },
                        "phoneNumber": {
                          "type": "string"
                        },
                        "to": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "optedInAt": {
                          "type": "string",
                          "description": "When this contact opted in, as a date. `opted_in_at`, `consentDate`, `consent_date`, `signupDate` and `signup_date` are read too. A value that is not a date is ignored."
                        }
                      },
                      "required": [
                        "phone"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 10000
                  },
                  "listId": {
                    "type": "string",
                    "description": "A contact list to add them to."
                  },
                  "optedInAt": {
                    "type": "string",
                    "description": "When every contact without its own `optedInAt` opted in, as a date."
                  }
                },
                "required": [
                  "contacts"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- ImportContactsResult: The import ran. Rows with a bad or repeated number are in `errors`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportContactsResult"
                },
                "examples": {
                  "default": {
                    "summary": "One row the workspace already has, one with a bad number and one repeated row.",
                    "value": {
                      "imported": 0,
                      "skippedDuplicates": 1,
                      "errors": [
                        {
                          "index": 1,
                          "phone": "12345",
                          "error": "Invalid E.164 format"
                        },
                        {
                          "index": 2,
                          "phone": "+15555550100",
                          "error": "Duplicate in import"
                        }
                      ],
                      "totalErrors": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `contacts` is missing, empty or has more than 10,000 rows.\n- `invalid_request`: No row has a usable phone number.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "index": {
                                "type": "integer",
                                "description": "The row's position in `contacts`, from 0."
                              },
                              "phone": {
                                "type": "string",
                                "description": "The row's phone number after spaces, dashes and parentheses were removed. For an empty number, the row's `phone` as sent, or an empty string."
                              },
                              "error": {
                                "type": "string",
                                "description": "Why the row was skipped. Known values: `Empty phone number`, `Invalid E.164 format`, `Duplicate in import`. More can be added at any time, so treat an unknown value as valid.",
                                "x-sendly-extensible-enum": [
                                  "Empty phone number",
                                  "Invalid E.164 format",
                                  "Duplicate in import"
                                ]
                              }
                            },
                            "required": [
                              "index",
                              "phone",
                              "error"
                            ]
                          },
                          "description": "The first 50 rows that were skipped, and why."
                        },
                        "totalErrors": {
                          "type": "integer",
                          "description": "How many rows were skipped."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errors",
                        "totalErrors"
                      ],
                      "title": "invalid_request: no valid rows",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An empty contacts array.",
                    "value": {
                      "error": "invalid_request",
                      "message": "contacts array is required"
                    }
                  },
                  "no-valid-rows": {
                    "summary": "Rows with no usable number.",
                    "value": {
                      "error": "invalid_request",
                      "message": "No valid contacts to import",
                      "errors": [
                        {
                          "index": 0,
                          "phone": "",
                          "error": "Empty phone number"
                        },
                        {
                          "index": 1,
                          "phone": "12345",
                          "error": "Invalid E.164 format"
                        }
                      ],
                      "totalErrors": 2
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The import failed. With a `listId` that names no list of the workspace, the contacts are created and then this is sent, with `message` `Contact list not found`. A row that is `null` also lands here, with the error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "unknown-list": {
                    "summary": "A row the workspace already has, with a listId that names no list.",
                    "value": {
                      "error": "internal_error",
                      "message": "Contact list not found"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacts/lookup": {
      "post": {
        "operationId": "lookupContacts",
        "summary": "Look up contacts' numbers",
        "description": "Starts a background carrier lookup of the workspace's contacts not looked up yet, or of one list's members, or with `force` of all of them again. Results fill `line_type`, `carrier_name` and `invalid_reason` within minutes; a landline or other number that cannot receive texts is flagged, unless someone marked it valid. Each number looked up costs 1 credit, test keys included, and is refunded when the lookup gives no result. The run stops when the balance runs out, and skips numbers past 5,000 lookups in a month. A second request for the same scope while one runs starts nothing. A key without a workspace looks up the workspace `X-Organization-Id` names or else its owner's personal workspace, not the contacts it created through `POST /api/v1/contacts`.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-session-rate-limit": {
          "limit": 5,
          "windowSeconds": 60
        },
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts",
          "method": "checkNumbers"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The scope of the lookup. An empty body looks up every contact not looked up yet.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "listId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Look up only this contact list's members."
                  },
                  "force": {
                    "type": "boolean",
                    "description": "`true` looks up numbers already looked up, too."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactLookupResult: The lookup started, or one for this scope is already running.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactLookupResult"
                },
                "examples": {
                  "already-running": {
                    "summary": "Built from lookupHandler in server/routes.ts: a lookup for the same scope is still running, so none was started. Not captured, since a lookup is charged per number.",
                    "value": {
                      "success": true,
                      "alreadyRunning": true,
                      "message": "A carrier lookup is already in progress for this scope. Results will appear as it completes."
                    }
                  },
                  "default": {
                    "summary": "Built from lookupHandler in server/routes.ts: a lookup was started. Not captured, since a lookup is charged per number.",
                    "value": {
                      "success": true,
                      "alreadyRunning": false,
                      "message": "Number lookup started. Carrier info will appear on contacts within a few minutes."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- listId must be a string: `listId` is not a string.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "listId must be a string"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "listId must be a string",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A listId that is not a string. Refused before any lookup starts.",
                    "value": {
                      "error": "listId must be a string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (contacts:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The caller has made more than 5 requests to this path in 60 seconds.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- Insufficient permissions: requires contacts:write, with a 500: The caller's workspace role lacks `contacts:write`, which is answered here and not with a 403.\n- Contacts lookup failed: The lookup could not be started, or the caller's workspace role lacks `contacts:write`, which is answered here and not with a 403.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Insufficient permissions: requires contacts:write"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`. Sent with a 500, so the code the envelope adds is `internal_error`, not `forbidden`.",
                      "title": "Insufficient permissions: requires contacts:write, with a 500",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds the error's own text, and there is no `message`. In a team workspace whose role lacks `contacts:write` it is `Insufficient permissions: requires contacts:write`.",
                      "title": "Contacts lookup failed",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacts/opt-out": {
      "post": {
        "operationId": "optOutContact",
        "summary": "Opt a contact out",
        "description": "Marks the phone number opted out, as a STOP reply does, so later sends to it are refused. Creates an opted-out contact when the workspace has none with this number.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The number to opt out.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone_number": {
                    "type": "string",
                    "pattern": "^\\+[1-9]\\d{6,14}$",
                    "description": "The phone number, in E.164 format. The server also takes one with spaces, dashes and parentheses, which it removes before checking."
                  }
                },
                "required": [
                  "phone_number"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactOptOutResult: The number is opted out.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactOptOutResult"
                },
                "examples": {
                  "default": {
                    "summary": "The test contact's number, opted out.",
                    "value": {
                      "phone_number": "+15555550100",
                      "opted_out": true,
                      "contact_id": "00000000-0000-4000-8000-000000000001"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `validation_error`: `phone_number` is missing, or is not in E.164 format once spaces, dashes and parentheses are removed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-phone": {
                    "summary": "A phone number that is not in E.164 format.",
                    "value": {
                      "error": "validation_error",
                      "message": "Invalid phone format. Must be E.164 (e.g., +15555550101)"
                    }
                  },
                  "default": {
                    "summary": "No phone_number.",
                    "value": {
                      "error": "validation_error",
                      "message": "phone_number is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The opt-out could not be stored.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacts/{id}": {
      "get": {
        "operationId": "getContact",
        "summary": "Get a contact",
        "description": "Returns one contact of the workspace and the contact lists it belongs to.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The contact's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactWithLists: The contact.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactWithLists"
                },
                "examples": {
                  "default": {
                    "summary": "The contact created above, in no list.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "phone_number": "+15555550100",
                      "name": "Ada Lovelace",
                      "email": null,
                      "metadata": {
                        "tier": "gold"
                      },
                      "opted_out": false,
                      "line_type": null,
                      "carrier_name": null,
                      "line_type_checked_at": null,
                      "invalid_reason": null,
                      "invalidated_at": null,
                      "user_marked_valid_at": null,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z",
                      "lists": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No contact with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no contact.",
                    "value": {
                      "error": "not_found",
                      "message": "Contact not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The contact could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateContact",
        "summary": "Update a contact",
        "description": "Changes the fields sent and leaves the rest. A new phone number clears what Sendly learned about the old one: the line type, the carrier, the invalid flag and `user_marked_valid_at`.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts",
          "method": "update"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The contact's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone_number": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "A new phone number, in E.164 format. Spaces, dashes and parentheses are removed first. `null` changes nothing."
                  },
                  "phoneNumber": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Read when `phone_number` is absent or `null`."
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "metadata": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "additionalProperties": {},
                    "description": "Replaces the stored metadata as a whole."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactWithLists: The contact, updated, with the lists it belongs to.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactWithLists"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the update answers through formatContactV1, the serializer GET uses, adding `opted_out`, `created_at` and `lists`. The production capture of 2026-10-02 predates that change. It was: A new name and metadata.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "phone_number": "+15555550100",
                      "name": "Ada King",
                      "email": null,
                      "metadata": {
                        "tier": "platinum"
                      },
                      "opted_out": false,
                      "line_type": null,
                      "carrier_name": null,
                      "line_type_checked_at": null,
                      "invalid_reason": null,
                      "invalidated_at": null,
                      "user_marked_valid_at": null,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z",
                      "lists": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `validation_error`: The new phone number is not in E.164 format once spaces, dashes and parentheses are removed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A new phone number that is not in E.164 format.",
                    "value": {
                      "error": "validation_error",
                      "message": "Invalid phone format. Must be E.164 format (e.g., +15555550101)"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No contact with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no contact.",
                    "value": {
                      "error": "not_found",
                      "message": "Contact not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `conflict`: Another contact of the workspace already has the new phone number.\n- `contact_opted_out`: The contact opted out, so its phone number cannot change. Its other fields can.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "conflict"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "existing_id": {
                          "type": "string",
                          "description": "The contact that already has this phone number."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "existing_id"
                      ],
                      "title": "conflict: phone number taken",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "conflict"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "contact_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "contact_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "contact_opted_out"
                      ]
                    }
                  ]
                },
                "examples": {
                  "opted-out": {
                    "summary": "A new phone number for the contact opted out above.",
                    "value": {
                      "error": "contact_opted_out",
                      "message": "This contact has opted out, so its phone number cannot be changed. Create a new contact for the new number."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The contact could not be updated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteContact",
        "summary": "Delete a contact",
        "description": "Deletes the contact and takes it out of every contact list.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts",
          "method": "delete"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The contact's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.\n\n- The contact was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (contacts:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No contact with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no contact.",
                    "value": {
                      "error": "not_found",
                      "message": "Contact not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The contact could not be deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacts/{id}/mark-valid": {
      "post": {
        "operationId": "markContactValid",
        "summary": "Mark a contact valid",
        "description": "Clears the contact's invalid flag and sets `userMarkedValidAt`, so a failed send or a lookup never flags it again. It does both even when the contact was not flagged. Sends `contact.marked_valid` only when a flag was cleared. It looks the contact up in the key's workspace, or for a key without one in the workspace `X-Organization-Id` names or else its owner's personal workspace, so a contact a workspace-less key created through `POST /api/v1/contacts` is not found here.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "contacts:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "contacts",
          "method": "markValid"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The contact's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ContactRecord: The contact, with its flag cleared.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactRecord"
                },
                "examples": {
                  "default": {
                    "summary": "A contact of the key owner's personal workspace that was never flagged.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": "00000000-0000-4000-8000-000000000004",
                      "phoneNumber": "+15555550100",
                      "name": "Ada Lovelace",
                      "email": null,
                      "metadata": {},
                      "optedOut": false,
                      "optedOutAt": null,
                      "optedOutKeyword": null,
                      "optedInAt": null,
                      "optedInMethod": null,
                      "optedInSource": null,
                      "lineType": null,
                      "carrierName": null,
                      "lineTypeCheckedAt": null,
                      "invalidReason": null,
                      "invalidatedAt": null,
                      "userMarkedValidAt": "2026-01-01T00:00:00.000Z",
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- Insufficient permissions: requires contacts:write: The caller's workspace role lacks `contacts:write`.\n- Contacts request failed: The caller's workspace role lacks `contacts:write`, or the update failed.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Insufficient permissions: requires contacts:write"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "forbidden"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Insufficient permissions: requires contacts:write",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "forbidden"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "forbidden"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds the error's own text, and there is no `message`. In a team workspace whose role lacks `contacts:write` it is `Insufficient permissions: requires contacts:write`, the only text that carries a code here.",
                      "title": "Contacts request failed",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "forbidden"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (contacts:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- Contact not found: No contact with this id belongs to the workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Contact not found"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "not_found"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "`error` holds a sentence, and there is no `message`.",
                  "title": "Contact not found",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "not_found"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no contact.",
                    "value": {
                      "error": "Contact not found"
                    }
                  },
                  "v1-contact": {
                    "summary": "The contact this workspace-less key created through POST /api/v1/contacts, which mark-valid looks for in the personal workspace.",
                    "value": {
                      "error": "Contact not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations": {
      "get": {
        "operationId": "listConversations",
        "summary": "List conversations",
        "description": "Lists the account's conversations, the one with the newest message first, after any with no message yet. A test key lists only sandbox conversations: those with at least one message, every one of them simulated. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "offset-has-more",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size, up to 100. Defaults to 50, which 0 or a value that is not a number also gives. A negative value fails with a 500."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many conversations to skip. A negative value fails with a 500."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only conversations with this status, such as `active`."
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only conversations with this label id."
            },
            "required": false,
            "name": "label",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ConversationList: A page of conversations.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationList"
                },
                "examples": {
                  "default": {
                    "summary": "The conversations with a label only the capture's conversation has.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "userId": "00000000-0000-4000-8000-000000000003",
                          "organizationId": null,
                          "phoneNumber": "+15555550100",
                          "status": "active",
                          "unreadCount": 0,
                          "messageCount": 3,
                          "lastMessageText": "Your Sendly code is 123456",
                          "lastMessageAt": "2026-01-01T00:00:00.000Z",
                          "lastMessageDirection": "outbound",
                          "channel": "sms",
                          "metadata": {},
                          "tags": [],
                          "contactId": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z",
                          "isGroup": false
                        }
                      ],
                      "pagination": {
                        "total": 1,
                        "limit": 1,
                        "offset": 0,
                        "hasMore": false
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: Reading or writing the conversation failed. `message` is the database error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A negative offset, which the database refuses.",
                    "value": {
                      "error": "internal_error",
                      "message": "OFFSET must not be negative"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations/{id}": {
      "get": {
        "operationId": "getConversation",
        "summary": "Get a conversation",
        "description": "Returns one conversation, and with `include_messages=true` a page of its messages: live ones for a live key, simulated ones for a test key. A test key gets only a sandbox conversation, one with at least one message, every one of them simulated. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "`true` adds `messages`. Any other value leaves it out."
            },
            "required": false,
            "name": "include_messages",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Messages per page, up to 100. Defaults to 50, which 0 or a value that is not a number also gives. A negative value fails with a 500."
            },
            "required": false,
            "name": "message_limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many messages to skip. A negative value fails with a 500."
            },
            "required": false,
            "name": "message_offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ConversationWithMessages: The conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationWithMessages"
                },
                "examples": {
                  "default": {
                    "summary": "A conversation with a sandbox number, without its messages.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "phoneNumber": "+15555550100",
                      "status": "active",
                      "unreadCount": 0,
                      "messageCount": 3,
                      "lastMessageText": "Your Sendly code is 123456",
                      "lastMessageAt": "2026-01-01T00:00:00.000Z",
                      "lastMessageDirection": "outbound",
                      "channel": "sms",
                      "metadata": {},
                      "tags": [],
                      "contactId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "isGroup": false
                    }
                  },
                  "with-messages": {
                    "summary": "The same conversation with include_messages=true: its messages are all simulated, so the thread is empty.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "phoneNumber": "+15555550100",
                      "status": "active",
                      "unreadCount": 0,
                      "messageCount": 3,
                      "lastMessageText": "Your Sendly code is 123456",
                      "lastMessageAt": "2026-01-01T00:00:00.000Z",
                      "lastMessageDirection": "outbound",
                      "channel": "sms",
                      "metadata": {},
                      "tags": [],
                      "contactId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "isGroup": false,
                      "messages": {
                        "data": [],
                        "pagination": {
                          "total": 0,
                          "limit": 5,
                          "offset": 0,
                          "hasMore": false
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.\n- `not_found`: No conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation.",
                    "value": {
                      "error": "not_found",
                      "message": "Conversation not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: Reading or writing the conversation failed. `message` is the database error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateConversation",
        "summary": "Update a conversation",
        "description": "Replaces the conversation's `metadata`, its `tags`, or both. A body with neither only touches `updatedAt`. A test key can update only a sandbox conversation. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "update"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to replace.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateConversationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- Conversation: The updated conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "examples": {
                  "default": {
                    "summary": "New metadata and tags.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "phoneNumber": "+15555550100",
                      "status": "active",
                      "unreadCount": 0,
                      "messageCount": 3,
                      "lastMessageText": "Your Sendly code is 123456",
                      "lastMessageAt": "2026-01-01T00:00:00.000Z",
                      "lastMessageDirection": "outbound",
                      "channel": "sms",
                      "metadata": {
                        "source": "contract-capture"
                      },
                      "tags": [
                        "contract-capture"
                      ],
                      "contactId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `metadata` is not a JSON object, or `tags` is not an array of strings.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "tags is a string, not an array.",
                    "value": {
                      "error": "invalid_request",
                      "message": "tags must be an array of strings"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.\n- `not_found`: No conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation.",
                    "value": {
                      "error": "not_found",
                      "message": "Conversation not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: Reading or writing the conversation failed. `message` is the database error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations/{id}/close": {
      "post": {
        "operationId": "closeConversation",
        "summary": "Close a conversation",
        "description": "Sets the status to `closed`. A closed conversation still receives messages, and the next inbound message makes it `active` again. A test key can change only a sandbox conversation. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "close"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Conversation: The closed conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "examples": {
                  "default": {
                    "summary": "Closes the conversation.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "phoneNumber": "+15555550100",
                      "status": "closed",
                      "unreadCount": 0,
                      "messageCount": 3,
                      "lastMessageText": "Your Sendly code is 123456",
                      "lastMessageAt": "2026-01-01T00:00:00.000Z",
                      "lastMessageDirection": "outbound",
                      "channel": "sms",
                      "metadata": {
                        "source": "contract-capture"
                      },
                      "tags": [
                        "contract-capture"
                      ],
                      "contactId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.\n- `not_found`: No conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation.",
                    "value": {
                      "error": "not_found",
                      "message": "Conversation not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: Reading or writing the conversation failed. `message` is the database error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations/{id}/context": {
      "get": {
        "operationId": "getConversationContext",
        "summary": "Get a conversation's context",
        "description": "Returns the conversation as plain text for a language model, from its newest messages, oldest first, so a long thread is cut at its start. A test key reads only a sandbox conversation, and only its simulated messages. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "getContext"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "description": "How many messages to read, up to 50. Defaults to 20, which 0 or a value that is not a number also gives. A negative value fails with a 500."
            },
            "required": false,
            "name": "max_messages",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ConversationContext: The conversation's context.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationContext"
                },
                "examples": {
                  "default": {
                    "summary": "The context of a conversation of simulated outbound messages.",
                    "value": {
                      "context": "[2026-10-02 23:48] Business: Your Sendly code is 123456\n[2026-10-02 23:48] Business: Your Sendly code is 123456\n[2026-10-03 05:17] Business: Your Sendly code is 123456\n\nBusiness: Sendly\nWhat they do: Two-factor authentication codes, suspicious login alerts, and account activity confirmations to keep user accounts secure",
                      "conversation": {
                        "id": "00000000-0000-4000-8000-000000000002",
                        "phoneNumber": "+15555550100",
                        "status": "active",
                        "messageCount": 3,
                        "unreadCount": 0
                      },
                      "tokenEstimate": 81,
                      "business": {
                        "name": "Sendly",
                        "useCase": "Two-factor authentication codes, suspicious login alerts, and account activity confirmations to keep user accounts secure"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.\n- `not_found`: No conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation.",
                    "value": {
                      "error": "not_found",
                      "message": "Conversation not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: Reading or writing the conversation failed. `message` is the database error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations/{id}/labels": {
      "post": {
        "operationId": "addConversationLabels",
        "summary": "Add labels to a conversation",
        "description": "Adds labels to the conversation and returns every label of the key's workspace it now has. Every label must belong to the key's workspace. A test key can label only a sandbox conversation. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "addLabels"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The labels to add.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddConversationLabelsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- Every label on the conversation, in no set order.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "The label's id."
                          },
                          "userId": {
                            "type": "string",
                            "description": "The account that owns the label."
                          },
                          "organizationId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "description": "A hex color, such as `#6b7280`."
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "When the label was created. ISO 8601, in UTC."
                          }
                        },
                        "required": [
                          "id",
                          "userId",
                          "organizationId",
                          "name",
                          "color",
                          "description",
                          "createdAt"
                        ]
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Adds the capture's label, which the conversation keeps once.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "userId": "00000000-0000-4000-8000-000000000003",
                          "organizationId": null,
                          "name": "contract-capture-conversations-00000000-0000-4000-8000-000000000006",
                          "color": "#6b7280",
                          "description": null,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `labelIds` is missing, not an array, or empty.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An empty labelIds array.",
                    "value": {
                      "error": "invalid_request",
                      "message": "labelIds array is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account, or no conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.\n- `not_found`: A `labelIds` entry names no label of the key's workspace. Nothing is added.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations/{id}/labels/{labelId}": {
      "delete": {
        "operationId": "removeConversationLabel",
        "summary": "Remove a label from a conversation",
        "description": "Removes one label from the conversation. A label the conversation does not have answers 204 too. A test key can change only a sandbox conversation. A database error gets no answer at all: the request fails without a response. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "removeLabel"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The label's id."
            },
            "required": true,
            "name": "labelId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.\n\n- The label is not on the conversation, whether or not it was before.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account, or no conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation. Runs last: the capture's label is deleted first.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations/{id}/mark-read": {
      "post": {
        "operationId": "markConversationRead",
        "summary": "Mark a conversation read",
        "description": "Sets `unreadCount` to 0. A test key can change only a sandbox conversation. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "markRead"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Conversation: The conversation, with `unreadCount` 0.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "examples": {
                  "default": {
                    "summary": "Marks the conversation read.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "phoneNumber": "+15555550100",
                      "status": "active",
                      "unreadCount": 0,
                      "messageCount": 3,
                      "lastMessageText": "Your Sendly code is 123456",
                      "lastMessageAt": "2026-01-01T00:00:00.000Z",
                      "lastMessageDirection": "outbound",
                      "channel": "sms",
                      "metadata": {
                        "source": "contract-capture"
                      },
                      "tags": [
                        "contract-capture"
                      ],
                      "contactId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.\n- `not_found`: No conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation.",
                    "value": {
                      "error": "not_found",
                      "message": "Conversation not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: Reading or writing the conversation failed. `message` is the database error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations/{id}/messages": {
      "post": {
        "operationId": "replyToConversation",
        "summary": "Reply to a conversation",
        "description": "Sends an SMS or MMS to the conversation's phone number, exactly as `POST /api/v1/messages` would, and answers as it does. A test key simulates the send, and can reply only to a sandbox conversation. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "reply"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The reply.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplyToConversationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- SMS or MMS sent: The reply was accepted, or simulated.\n- Short code message sent: The reply was sent from the workspace's short code.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SmsSendResult"
                    },
                    {
                      "$ref": "#/components/schemas/ShortCodeSendResult"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key's reply, simulated as delivered.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000005",
                      "to": "+15555550100",
                      "from": "SENDLY-TEST",
                      "text": "Your Sendly code is 123456",
                      "status": "delivered",
                      "direction": "outbound",
                      "error": null,
                      "segments": 1,
                      "creditsUsed": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "metadata": {},
                      "simulated": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_request`: Neither `text` nor media, or a field the send refuses: `messageType`, `metadata`, the media URLs, or media to a destination outside the US and Canada.\n- `compliance_blocked`: The text has restricted (SHAFT) content.\n- `contact_opted_out`: The contact opted out.\n- `compliance_blocked`: A marketing message during the contact's quiet hours.\n- `compliance_blocked`: A short code marketing message during quiet hours.\n- `TRANSACTIONAL_MARKETING_MISMATCH`: A message marked transactional reads as marketing during quiet hours.\n- `unsupported_destination`: The contact's country is not supported, or a short code was asked to send outside the US.\n- `invalid_from_number`: `from` is not an active number of this workspace that can send here.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SHAFT_CONTENT_DETECTED"
                          ]
                        },
                        "category": {
                          "type": "string",
                          "description": "The restricted category the text matched. Known values: `sex`, `hate`, `alcohol`, `firearms`, `tobacco`, `cannabis`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "sex",
                            "hate",
                            "alcohol",
                            "firearms",
                            "tobacco",
                            "cannabis"
                          ]
                        },
                        "matchedTerms": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "category",
                        "matchedTerms",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: SHAFT content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "contact_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "contact_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "contact_opted_out"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "QUIET_HOURS_VIOLATION"
                          ]
                        },
                        "recipientTimezone": {
                          "type": "string"
                        },
                        "recipientLocalTime": {
                          "type": "string"
                        },
                        "quietHoursStart": {
                          "type": "string"
                        },
                        "quietHoursEnd": {
                          "type": "string"
                        },
                        "nextAllowedTime": {
                          "type": "string",
                          "format": "date-time",
                          "description": "The earliest time a marketing message may go. ISO 8601, in UTC."
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "recipientTimezone",
                        "recipientLocalTime",
                        "quietHoursStart",
                        "quietHoursEnd",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: quiet hours",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "QUIET_HOURS_VIOLATION"
                          ]
                        },
                        "recipientTimezone": {
                          "type": "string"
                        },
                        "nextAllowedTime": {
                          "type": "string",
                          "format": "date-time",
                          "description": "The earliest time a marketing message may go. ISO 8601, in UTC."
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "recipientTimezone",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: quiet hours, short code",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "TRANSACTIONAL_MARKETING_MISMATCH"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "matchedKeywords": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "suggestion": {
                          "type": "string"
                        },
                        "reason": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "transactional_marketing_mismatch"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "matchedKeywords",
                        "suggestion",
                        "reason"
                      ],
                      "description": "Has no `error` field: the code is in `code`.",
                      "title": "TRANSACTIONAL_MARKETING_MISMATCH",
                      "x-sendly-error-shape": "codeless",
                      "x-sendly-error-codes": [
                        "TRANSACTIONAL_MARKETING_MISMATCH"
                      ],
                      "x-sendly-proposed-codes": [
                        "transactional_marketing_mismatch"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "unsupported_destination"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "country": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The destination's country code, when known."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "country"
                      ],
                      "title": "unsupported_destination",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "unsupported_destination"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_from_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "INVALID_FROM_NUMBER"
                          ],
                          "description": "Present when the account could not send here at all; absent when the number is not usable for a US or Canada destination."
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_from_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_from_number"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Neither text nor media.",
                    "value": {
                      "error": "invalid_request",
                      "message": "text or mediaUrls required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: The balance does not cover the message.\n- `insufficient_credits`: Charging the message failed, as for `POST /api/v1/messages`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_credits"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "creditsNeeded": {
                          "type": "integer"
                        },
                        "currentBalance": {
                          "type": "integer"
                        },
                        "tier": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The destination's price tier. Known values: `domestic`, `tier1`, `tier2`, `tier3`, `tier4`, `tier5`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "domestic",
                            "tier1",
                            "tier2",
                            "tier3",
                            "tier4",
                            "tier5"
                          ]
                        },
                        "pricePerSms": {
                          "type": "number",
                          "description": "The price of one segment, in US dollars."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "creditsNeeded",
                        "currentBalance",
                        "tier",
                        "pricePerSms"
                      ],
                      "title": "insufficient_credits, with the price",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_credits"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientCreditsError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `feature_disabled`: MMS is not enabled for the account.\n- `ACCOUNT_UNDER_REVIEW`: A new account sent text that reads like a payment scam.\n- `destination_not_authorized`: The account's verification does not cover this destination.\n- `sender_not_authorized`: The `from` number is not authorized for this destination yet.\n- `registration_required`: The destination country needs a registered sender ID first.\n- `short_code_suspended`, `short_code_not_ready`, `short_code_cancelled`: The short code is suspended, cancelled, or not live yet.\n- `recipient_opted_out`: The contact opted out of the short code.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Your account has been flagged for review. Please contact support."
                          ]
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "ACCOUNT_UNDER_REVIEW"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "account_under_review"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error",
                        "code"
                      ],
                      "description": "`error` holds a sentence; the code is in `code`.",
                      "title": "ACCOUNT_UNDER_REVIEW",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [
                        "ACCOUNT_UNDER_REVIEW"
                      ],
                      "x-sendly-proposed-codes": [
                        "account_under_review"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "destination_not_authorized"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "DESTINATION_NOT_AUTHORIZED"
                          ]
                        },
                        "destinationCountry": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "destination_not_authorized",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "destination_not_authorized"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "sender_not_authorized"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SENDER_NOT_AUTHORIZED"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "sender_not_authorized",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "sender_not_authorized"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "registration_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SENDER_ID_NOT_REGISTERED"
                          ]
                        },
                        "countryCode": {
                          "type": "string"
                        },
                        "countryName": {
                          "type": "string"
                        },
                        "registrationUrl": {
                          "type": "string",
                          "description": "A dashboard path that starts the registration request."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "countryCode",
                        "countryName",
                        "registrationUrl"
                      ],
                      "title": "registration_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "registration_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_suspended",
                            "short_code_not_ready",
                            "short_code_cancelled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "short_code_suspended, short_code_not_ready, short_code_cancelled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_suspended",
                        "short_code_not_ready",
                        "short_code_cancelled"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "recipient_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "recipient_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "recipient_opted_out"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.\n- `not_found`: No conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation.",
                    "value": {
                      "error": "not_found",
                      "message": "Conversation not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `channel_not_supported`: The conversation is a WhatsApp thread, which this endpoint cannot reply to.\n- `group_reply_not_supported`: The conversation is a group, which this endpoint cannot reply to.\n- `undeliverable_number`: The contact is flagged as unable to receive texts.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "channel_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "channel_not_supported: WhatsApp conversation",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "channel_not_supported"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "group_reply_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "group_reply_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "group_reply_not_supported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "undeliverable_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "description": "Why the number cannot receive texts. Known values: `undeliverable_landline`, `undeliverable_invalid`, `undeliverable_non_sms`, `undeliverable_number`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "undeliverable_landline",
                            "undeliverable_invalid",
                            "undeliverable_non_sms",
                            "undeliverable_number"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "undeliverable_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "undeliverable_number"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The first reply's Idempotency-Key, reused with a different body.",
                    "value": {
                      "error": "idempotency_key_mismatch",
                      "message": "This idempotency key was already used with a different request body. Use a new key for different requests."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The send failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `short_code_send_failed`: The carrier network did not take the short code message. Nothing was sent and the charge was refunded.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "short_code_send_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "errorCode": {
                      "type": "string",
                      "description": "The error code, such as `E001`."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "errorCode"
                  ],
                  "title": "short_code_send_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "short_code_send_failed"
                  ],
                  "x-sendly-visibility": "preview"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations/{id}/reopen": {
      "post": {
        "operationId": "reopenConversation",
        "summary": "Reopen a conversation",
        "description": "Sets the status to `active`. A test key can change only a sandbox conversation. Behind the `conversations_api` flag.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "reopen"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Conversation: The reopened conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "examples": {
                  "default": {
                    "summary": "Reopens the closed conversation.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "phoneNumber": "+15555550100",
                      "status": "active",
                      "unreadCount": 0,
                      "messageCount": 3,
                      "lastMessageText": "Your Sendly code is 123456",
                      "lastMessageAt": "2026-01-01T00:00:00.000Z",
                      "lastMessageDirection": "outbound",
                      "channel": "sms",
                      "metadata": {
                        "source": "contract-capture"
                      },
                      "tags": [
                        "contract-capture"
                      ],
                      "contactId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.\n- `not_found`: No conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation.",
                    "value": {
                      "error": "not_found",
                      "message": "Conversation not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: Reading or writing the conversation failed. `message` is the database error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/conversations/{id}/suggest-replies": {
      "post": {
        "operationId": "suggestConversationReplies",
        "summary": "Suggest replies",
        "description": "Asks a language model for two or three short replies to the newest inbound message among the conversation's 10 newest messages, read oldest first; a test key reads only a sandbox conversation, and only its simulated messages. Behind the `ai_classification` flag, not `conversations_api`.",
        "tags": [
          "Conversations"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "conversations",
          "method": "suggestReplies"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The conversation's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Suggestions: The model suggested replies.\n- No suggestions: No reply could be suggested.\n- Turned off by the enterprise: The enterprise turned AI suggestions off for the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SuggestRepliesResult"
                    },
                    {
                      "$ref": "#/components/schemas/SuggestRepliesNone"
                    },
                    {
                      "$ref": "#/components/schemas/SuggestRepliesDisabled"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A conversation with no inbound message, so no reply is suggested and no model is asked.",
                    "value": {
                      "suggestions": []
                    }
                  },
                  "suggestions": {
                    "summary": "The model suggested replies. Built from suggestReplies in server/services/ai-suggest.ts: asking the model costs money, so this is never captured.",
                    "value": {
                      "suggestions": [
                        {
                          "text": "Thanks for letting us know. Your appointment is moved to 3pm tomorrow.",
                          "tone": "professional"
                        },
                        {
                          "text": "No problem! You're all set for 3pm tomorrow.",
                          "tone": "friendly"
                        },
                        {
                          "text": "Done: 3pm tomorrow.",
                          "tone": "concise"
                        }
                      ],
                      "basedOnMessageId": "00000000-0000-4000-8000-000000000004",
                      "model": "claude-sonnet-4-5-20250929"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: AI suggestions are not enabled for the account, or no conversation with this id belongs to the key's account or workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no conversation.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/countries": {
      "get": {
        "operationId": "listCountries",
        "summary": "List countries",
        "description": "Lists the countries Sendly sends SMS to, with each one's price tier, price per SMS segment and sender rules, and the price of every tier. It needs no API key. The list is fixed in the server and the same for every caller. It holds 51 countries, fewer than billing prices, so a country missing from it is not necessarily unreachable.",
        "tags": [
          "Countries"
        ],
        "security": [],
        "x-sendly-auth": "public",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- CountryList: Every listed country and every price tier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CountryList"
                },
                "examples": {
                  "default": {
                    "summary": "Every listed country and price tier, asked for with no Authorization header.",
                    "value": {
                      "countries": [
                        {
                          "code": "US",
                          "name": "United States",
                          "dial_code": "+1",
                          "tier": "domestic",
                          "credits_per_sms": 2,
                          "price_usd": 0.02,
                          "requires_registration": false,
                          "alpha_sender": "unknown"
                        },
                        {
                          "code": "CA",
                          "name": "Canada",
                          "dial_code": "+1",
                          "tier": "domestic",
                          "credits_per_sms": 2,
                          "price_usd": 0.02,
                          "requires_registration": false,
                          "alpha_sender": "unknown"
                        },
                        {
                          "code": "GB",
                          "name": "United Kingdom",
                          "dial_code": "+44",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "AU",
                          "name": "Australia",
                          "dial_code": "+61",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "SG",
                          "name": "Singapore",
                          "dial_code": "+65",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "CN",
                          "name": "China",
                          "dial_code": "+86",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": true,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "TH",
                          "name": "Thailand",
                          "dial_code": "+66",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "TR",
                          "name": "Turkey",
                          "dial_code": "+90",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "PL",
                          "name": "Poland",
                          "dial_code": "+48",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "PT",
                          "name": "Portugal",
                          "dial_code": "+351",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "CY",
                          "name": "Cyprus",
                          "dial_code": "+357",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "CO",
                          "name": "Colombia",
                          "dial_code": "+57",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "DK",
                          "name": "Denmark",
                          "dial_code": "+45",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "BR",
                          "name": "Brazil",
                          "dial_code": "+55",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "GR",
                          "name": "Greece",
                          "dial_code": "+30",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "SE",
                          "name": "Sweden",
                          "dial_code": "+46",
                          "tier": "tier1",
                          "credits_per_sms": 8,
                          "price_usd": 0.08,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "IN",
                          "name": "India",
                          "dial_code": "+91",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": true,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "HU",
                          "name": "Hungary",
                          "dial_code": "+36",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "CZ",
                          "name": "Czech Republic",
                          "dial_code": "+420",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "partial"
                        },
                        {
                          "code": "RO",
                          "name": "Romania",
                          "dial_code": "+40",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "partial"
                        },
                        {
                          "code": "FR",
                          "name": "France",
                          "dial_code": "+33",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "ES",
                          "name": "Spain",
                          "dial_code": "+34",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "JP",
                          "name": "Japan",
                          "dial_code": "+81",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "IT",
                          "name": "Italy",
                          "dial_code": "+39",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "AT",
                          "name": "Austria",
                          "dial_code": "+43",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "AR",
                          "name": "Argentina",
                          "dial_code": "+54",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "TW",
                          "name": "Taiwan",
                          "dial_code": "+886",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "NO",
                          "name": "Norway",
                          "dial_code": "+47",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "FI",
                          "name": "Finland",
                          "dial_code": "+358",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "HK",
                          "name": "Hong Kong",
                          "dial_code": "+852",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "IE",
                          "name": "Ireland",
                          "dial_code": "+353",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "CH",
                          "name": "Switzerland",
                          "dial_code": "+41",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "CL",
                          "name": "Chile",
                          "dial_code": "+56",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "ZA",
                          "name": "South Africa",
                          "dial_code": "+27",
                          "tier": "tier2",
                          "credits_per_sms": 12,
                          "price_usd": 0.12,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "DE",
                          "name": "Germany",
                          "dial_code": "+49",
                          "tier": "tier3",
                          "credits_per_sms": 16,
                          "price_usd": 0.16,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "NL",
                          "name": "Netherlands",
                          "dial_code": "+31",
                          "tier": "tier3",
                          "credits_per_sms": 16,
                          "price_usd": 0.16,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "BE",
                          "name": "Belgium",
                          "dial_code": "+32",
                          "tier": "tier3",
                          "credits_per_sms": 16,
                          "price_usd": 0.16,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "NZ",
                          "name": "New Zealand",
                          "dial_code": "+64",
                          "tier": "tier3",
                          "credits_per_sms": 16,
                          "price_usd": 0.16,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "AE",
                          "name": "UAE",
                          "dial_code": "+971",
                          "tier": "tier3",
                          "credits_per_sms": 16,
                          "price_usd": 0.16,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "MX",
                          "name": "Mexico",
                          "dial_code": "+52",
                          "tier": "tier3",
                          "credits_per_sms": 16,
                          "price_usd": 0.16,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "VN",
                          "name": "Vietnam",
                          "dial_code": "+84",
                          "tier": "tier4",
                          "credits_per_sms": 24,
                          "price_usd": 0.24,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "SA",
                          "name": "Saudi Arabia",
                          "dial_code": "+966",
                          "tier": "tier4",
                          "credits_per_sms": 24,
                          "price_usd": 0.24,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "PH",
                          "name": "Philippines",
                          "dial_code": "+63",
                          "tier": "tier5",
                          "credits_per_sms": 48,
                          "price_usd": 0.48,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "KE",
                          "name": "Kenya",
                          "dial_code": "+254",
                          "tier": "tier5",
                          "credits_per_sms": 48,
                          "price_usd": 0.48,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "IL",
                          "name": "Israel",
                          "dial_code": "+972",
                          "tier": "tier5",
                          "credits_per_sms": 48,
                          "price_usd": 0.48,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        },
                        {
                          "code": "MY",
                          "name": "Malaysia",
                          "dial_code": "+60",
                          "tier": "tier5",
                          "credits_per_sms": 48,
                          "price_usd": 0.48,
                          "requires_registration": false,
                          "alpha_sender": "replaced"
                        },
                        {
                          "code": "EG",
                          "name": "Egypt",
                          "dial_code": "+20",
                          "tier": "tier5",
                          "credits_per_sms": 48,
                          "price_usd": 0.48,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "NG",
                          "name": "Nigeria",
                          "dial_code": "+234",
                          "tier": "tier5",
                          "credits_per_sms": 48,
                          "price_usd": 0.48,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "PK",
                          "name": "Pakistan",
                          "dial_code": "+92",
                          "tier": "tier5",
                          "credits_per_sms": 48,
                          "price_usd": 0.48,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "ID",
                          "name": "Indonesia",
                          "dial_code": "+62",
                          "tier": "tier5",
                          "credits_per_sms": 48,
                          "price_usd": 0.48,
                          "requires_registration": true,
                          "alpha_sender": "registration_required"
                        },
                        {
                          "code": "MV",
                          "name": "Maldives",
                          "dial_code": "+960",
                          "tier": "tier5",
                          "credits_per_sms": 48,
                          "price_usd": 0.48,
                          "requires_registration": false,
                          "alpha_sender": "supported"
                        }
                      ],
                      "tiers": {
                        "domestic": {
                          "credits": 2,
                          "price_usd": 0.02,
                          "description": "US & Canada"
                        },
                        "tier1": {
                          "credits": 8,
                          "price_usd": 0.08,
                          "description": "14 countries"
                        },
                        "tier2": {
                          "credits": 12,
                          "price_usd": 0.12,
                          "description": "18 countries"
                        },
                        "tier3": {
                          "credits": 16,
                          "price_usd": 0.16,
                          "description": "6 countries"
                        },
                        "tier4": {
                          "credits": 24,
                          "price_usd": 0.24,
                          "description": "5 countries"
                        },
                        "tier5": {
                          "credits": 48,
                          "price_usd": 0.48,
                          "description": "6 countries"
                        }
                      },
                      "total_countries": 51
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyError"
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A GET with a body that is not valid JSON, answered by the body parser. Captured from the origin: the edge answers a GET with a body itself.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnhandledServerError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/credits": {
      "get": {
        "operationId": "getCredits",
        "summary": "Get the credit balance",
        "description": "Returns the credit balance the key spends from: its workspace's, the enterprise pool's when the workspace shares one, or the account's own for a key with no workspace. Any key can call it, whatever its scopes.",
        "tags": [
          "Credits"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "getCredits"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- CreditBalance: The balance.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditBalance"
                },
                "examples": {
                  "default": {
                    "summary": "The balance of a test key with no workspace: the account's own, prepaid.",
                    "value": {
                      "balance": 170,
                      "reservedBalance": 0,
                      "availableBalance": 170,
                      "billingMode": "prepaid"
                    }
                  },
                  "pooled": {
                    "summary": "Built from the handler: a workspace whose enterprise account shares one pool, with 300 credits of accrued overage and a 5,000 credit overage cap. Not captured, since the test key has no workspace.",
                    "value": {
                      "balance": -300,
                      "reservedBalance": 20,
                      "availableBalance": 4680,
                      "billingMode": "pooled"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  },
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The balance could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/credits/transactions": {
      "get": {
        "operationId": "listCreditTransactions",
        "summary": "List credit transactions",
        "description": "Lists the credit transactions of the key's workspace, or of the account for a key with no workspace, newest first. Any key can call it, whatever its scopes.",
        "tags": [
          "Credits"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-paged-by": [
          "limit",
          "offset",
          "page"
        ],
        "x-sendly-sdk": {
          "resource": "account",
          "method": "getCreditTransactions"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size, 1 to 100. Defaults to 50, which is also what 0 or a value that is not a number gives. A value below 1 is raised to 1, and one above 100 is lowered to 100."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many transactions to skip. Ignored when `page` is set."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "The page to return, starting at 1. Takes precedence over `offset`."
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only transactions of this type, matched exactly after trimming. An unknown type returns an empty list, and a blank one lists every type."
            },
            "required": false,
            "name": "type",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- CreditTransactionList: A page of transactions.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditTransactionList"
                },
                "examples": {
                  "default": {
                    "summary": "The three newest transactions of a test key with no workspace: the account's own, which has none.",
                    "value": {
                      "transactions": []
                    }
                  },
                  "unknown-type": {
                    "summary": "A type no transaction has, which lists nothing.",
                    "value": {
                      "transactions": []
                    }
                  },
                  "with-transactions": {
                    "summary": "Built from the handler and serializer: a workspace's two newest transactions. Not captured, since the test key's own account has none.",
                    "value": {
                      "transactions": [
                        {
                          "id": "00000000-0000-4000-8000-000000000020",
                          "amount": -2,
                          "balance_after": 1498,
                          "type": "usage",
                          "description": "SMS to US",
                          "created_at": "2026-01-02T00:00:00.000Z"
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000021",
                          "amount": 1000,
                          "balance_after": 1500,
                          "type": "purchase",
                          "description": "Purchased 1,000 credits ($10.00)",
                          "created_at": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key passed in the URL.",
                    "value": {
                      "error": "invalid_request",
                      "message": "API keys must not be passed in URL parameters. Use the Authorization header instead."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The transactions could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/credits/transfer": {
      "post": {
        "operationId": "transferCredits",
        "summary": "Transfer credits to another workspace",
        "description": "Moves credits from the key's workspace to another workspace, when the key's user owns both. It moves the workspaces' own balances, also for a workspace whose enterprise account shares a pool. Any key can call it, whatever its scopes, and a test key moves real credits too.",
        "tags": [
          "Credits"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "account",
          "method": "transferCredits"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "Where to move the credits, and how many.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransferCreditsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- CreditTransferResult: The credits were moved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditTransferResult"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: 500 credits moved between two workspaces the key's user owns. Not captured, since a capture would move real credits.",
                    "value": {
                      "success": true,
                      "amount": 500,
                      "sourceBalance": 1500,
                      "targetBalance": 700
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_request`: The key has no workspace, `targetOrganizationId` is missing, empty or not a string, `amount` is not a positive whole JSON number, or the target is the key's own workspace. Checked in that order, so a key with no workspace is refused whatever the body.\n- `insufficient_credits`: The key's workspace has fewer credits than `amount`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_credits"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "Sent with status 400, where a send answers 402.",
                      "title": "insufficient_credits: transfer",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_credits"
                      ]
                    }
                  ]
                },
                "examples": {
                  "insufficient-credits": {
                    "summary": "Built from the handler: the key's workspace has fewer credits than the amount. Not captured, since it needs a workspace key.",
                    "value": {
                      "error": "insufficient_credits",
                      "message": "Insufficient credits for transfer"
                    }
                  },
                  "invalid-json": {
                    "summary": "A body that is not valid JSON, answered by the body parser.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  },
                  "default": {
                    "summary": "A test key with no workspace, refused before anything is read or moved. The target is a workspace that does not exist.",
                    "value": {
                      "error": "invalid_request",
                      "message": "API key must be scoped to a workspace"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: The key's user does not own the key's workspace, or the target workspace does not exist or is not theirs.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the target workspace does not exist or the key's user does not own it. Not captured, since it needs a workspace key.",
                    "value": {
                      "error": "forbidden",
                      "message": "You must own the target workspace"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                },
                "examples": {
                  "default": {
                    "summary": "The first request's Idempotency-Key, reused with a different body.",
                    "value": {
                      "error": "idempotency_key_mismatch",
                      "message": "This idempotency key was already used with a different request body. Use a new key for different requests."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The transfer failed unexpectedly, such as when either workspace has no credit balance of its own yet. Nothing was moved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/drafts": {
      "get": {
        "operationId": "listDrafts",
        "summary": "List drafts",
        "description": "Lists the workspace's drafts, newest first. A test key lists only drafts on sandbox conversations: those with at least one message, every one of them simulated.",
        "tags": [
          "Drafts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "total",
        "x-sendly-sdk": {
          "resource": "drafts",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Only drafts for this conversation."
            },
            "required": false,
            "name": "conversation_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only drafts with this status: `pending`, `approved` or `rejected`."
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size. Defaults to 50; a value above 100 is lowered to 100."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many drafts to skip."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- MessageDraftList: A page of drafts, with the total that match.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageDraftList"
                },
                "examples": {
                  "default": {
                    "summary": "The drafts on the fictional number's conversation.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "userId": "00000000-0000-4000-8000-000000000003",
                          "organizationId": null,
                          "conversationId": "00000000-0000-4000-8000-000000000001",
                          "text": "Your Sendly code is 123456",
                          "mediaUrls": [],
                          "metadata": {
                            "orderId": "A-100"
                          },
                          "status": "pending",
                          "source": "agent",
                          "createdBy": "00000000-0000-4000-8000-000000000004",
                          "reviewedBy": null,
                          "reviewedAt": null,
                          "rejectionReason": null,
                          "messageId": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z"
                        }
                      ],
                      "pagination": {
                        "total": 1
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `conversation_id` or `status` is given more than once, or holds a NUL character.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createDraft",
        "summary": "Create a draft",
        "description": "Saves a reply to a conversation for a person to review. Nothing is sent until the draft is approved. A test key can save one only on a sandbox conversation.",
        "tags": [
          "Drafts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "drafts",
          "method": "create"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "requestBody": {
          "description": "The draft to save.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDraftRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- MessageDraft: The draft was saved as `pending`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageDraft"
                },
                "examples": {
                  "default": {
                    "summary": "A pending draft on a conversation with a fictional number.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "conversationId": "00000000-0000-4000-8000-000000000001",
                      "text": "Your Sendly code is 123456",
                      "mediaUrls": [],
                      "metadata": {
                        "orderId": "A-100"
                      },
                      "status": "pending",
                      "source": "agent",
                      "createdBy": "00000000-0000-4000-8000-000000000004",
                      "reviewedBy": null,
                      "reviewedAt": null,
                      "rejectionReason": null,
                      "messageId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `conversationId` or `text` is missing or empty, `conversationId` or `text` is not a string, or `text` holds a NUL character.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The text is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "conversationId and text are required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.\n- `not_found`: No conversation with this id belongs to the key's workspace, or the key is a test key and the conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A conversation id that matches no conversation.",
                    "value": {
                      "error": "not_found",
                      "message": "Conversation not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/drafts/{id}": {
      "get": {
        "operationId": "getDraft",
        "summary": "Get a draft",
        "description": "Returns one draft of this workspace, in any status. A test key gets only a draft on a sandbox conversation.",
        "tags": [
          "Drafts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "drafts",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The draft's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- MessageDraft: The draft.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageDraft"
                },
                "examples": {
                  "default": {
                    "summary": "A pending draft.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "conversationId": "00000000-0000-4000-8000-000000000001",
                      "text": "Your Sendly code is 123456",
                      "mediaUrls": [],
                      "metadata": {
                        "orderId": "A-100"
                      },
                      "status": "pending",
                      "source": "agent",
                      "createdBy": "00000000-0000-4000-8000-000000000004",
                      "reviewedBy": null,
                      "reviewedAt": null,
                      "rejectionReason": null,
                      "messageId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No draft with this id belongs to the key's workspace, the key is a test key and the draft's conversation is not a sandbox conversation, or the id is empty or holds a NUL character.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no draft.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateDraft",
        "summary": "Update a draft",
        "description": "Edits a pending draft's text, media or metadata. A test key can edit only a draft on a sandbox conversation.",
        "tags": [
          "Drafts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "drafts",
          "method": "update"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The draft's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDraftRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- MessageDraft: The edited draft.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageDraft"
                },
                "examples": {
                  "default": {
                    "summary": "The pending draft's text and metadata, edited.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "conversationId": "00000000-0000-4000-8000-000000000001",
                      "text": "Your Sendly code is 123456",
                      "mediaUrls": [],
                      "metadata": {
                        "orderId": "A-101"
                      },
                      "status": "pending",
                      "source": "agent",
                      "createdBy": "00000000-0000-4000-8000-000000000004",
                      "reviewedBy": null,
                      "reviewedAt": null,
                      "rejectionReason": null,
                      "messageId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `text` is sent and is not a non-empty string, or holds a NUL character.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No draft with this id belongs to the key's workspace, the draft is no longer pending, the key is a test key and the draft's conversation is not a sandbox conversation, or the id is empty or holds a NUL character.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no draft.",
                    "value": {
                      "error": "not_found",
                      "message": "Draft not found or not pending"
                    }
                  },
                  "not-pending": {
                    "summary": "A draft that was already rejected.",
                    "value": {
                      "error": "not_found",
                      "message": "Draft not found or not pending"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/drafts/{id}/approve": {
      "post": {
        "operationId": "approveDraft",
        "summary": "Approve a draft",
        "description": "Approves a pending draft and sends it as an SMS, or an MMS when it has media, to the conversation's contact, the way `POST /api/v1/messages` sends it with no `from` and no `messageType`, so as a marketing message. A test key simulates the send, and can approve only a draft on a sandbox conversation. When the send is refused with a 4xx, the draft goes back to `pending` and the send's own error is returned. When it fails with a 5xx, the draft stays `approved` without a message, in case the message went out.",
        "tags": [
          "Drafts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "drafts",
          "method": "approve"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The draft's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ApprovedMessageDraft: The draft was approved and its message sent, or simulated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovedMessageDraft"
                },
                "examples": {
                  "default": {
                    "summary": "The pending draft, approved and sent as a simulated SMS by a test key.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "conversationId": "00000000-0000-4000-8000-000000000001",
                      "text": "Your Sendly code is 123456",
                      "mediaUrls": [],
                      "metadata": {
                        "orderId": "A-101"
                      },
                      "status": "approved",
                      "source": "agent",
                      "createdBy": "00000000-0000-4000-8000-000000000004",
                      "reviewedBy": "00000000-0000-4000-8000-000000000003",
                      "reviewedAt": "2026-01-01T00:00:00.000Z",
                      "rejectionReason": null,
                      "messageId": "00000000-0000-4000-8000-000000000007",
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "message": {
                        "id": "00000000-0000-4000-8000-000000000007",
                        "to": "+15555550100",
                        "from": "SENDLY-TEST",
                        "text": "Your Sendly code is 123456",
                        "status": "delivered",
                        "direction": "outbound",
                        "error": null,
                        "segments": 1,
                        "creditsUsed": 0,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "metadata": {
                          "orderId": "A-101"
                        },
                        "simulated": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_request`: The send refused the draft: no text and no media, invalid media URLs, media to a destination outside the US and Canada, metadata over 4 KB, or a contact number that is not a valid phone number.\n- `compliance_blocked`: The text has restricted (SHAFT) content.\n- `contact_opted_out`: The contact opted out.\n- `compliance_blocked`: It is quiet hours where the contact is.\n- `unsupported_destination`: The contact's country is not supported.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SHAFT_CONTENT_DETECTED"
                          ]
                        },
                        "category": {
                          "type": "string",
                          "description": "The restricted category the text matched. Known values: `sex`, `hate`, `alcohol`, `firearms`, `tobacco`, `cannabis`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "sex",
                            "hate",
                            "alcohol",
                            "firearms",
                            "tobacco",
                            "cannabis"
                          ]
                        },
                        "matchedTerms": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "category",
                        "matchedTerms",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: SHAFT content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "contact_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "contact_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "contact_opted_out"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "QUIET_HOURS_VIOLATION"
                          ]
                        },
                        "recipientTimezone": {
                          "type": "string"
                        },
                        "recipientLocalTime": {
                          "type": "string"
                        },
                        "quietHoursStart": {
                          "type": "string"
                        },
                        "quietHoursEnd": {
                          "type": "string"
                        },
                        "nextAllowedTime": {
                          "type": "string",
                          "format": "date-time",
                          "description": "The earliest time a marketing message may go. ISO 8601, in UTC."
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "recipientTimezone",
                        "recipientLocalTime",
                        "quietHoursStart",
                        "quietHoursEnd",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: quiet hours",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "unsupported_destination"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "country": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The destination's country code, when known."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "country"
                      ],
                      "title": "unsupported_destination",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "unsupported_destination"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: The balance does not cover the message.\n- `insufficient_credits`: Charging the message failed. `message` is the charge's own error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_credits"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "creditsNeeded": {
                          "type": "integer"
                        },
                        "currentBalance": {
                          "type": "integer"
                        },
                        "tier": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The destination's price tier. Known values: `domestic`, `tier1`, `tier2`, `tier3`, `tier4`, `tier5`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "domestic",
                            "tier1",
                            "tier2",
                            "tier3",
                            "tier4",
                            "tier5"
                          ]
                        },
                        "pricePerSms": {
                          "type": "number",
                          "description": "The price of one segment, in US dollars."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "creditsNeeded",
                        "currentBalance",
                        "tier",
                        "pricePerSms"
                      ],
                      "title": "insufficient_credits, with the price",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_credits"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientCreditsError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `feature_disabled`: The draft has media and MMS is not enabled for the account.\n- `ACCOUNT_UNDER_REVIEW`: A new account's text reads like a payment scam. A workspace key also suspends the workspace.\n- `destination_not_authorized`: The account's verification does not cover the contact's country.\n- `registration_required`: The contact's country needs a registered sender ID first.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Your account has been flagged for review. Please contact support."
                          ]
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "ACCOUNT_UNDER_REVIEW"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "account_under_review"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error",
                        "code"
                      ],
                      "description": "`error` holds a sentence; the code is in `code`.",
                      "title": "ACCOUNT_UNDER_REVIEW",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [
                        "ACCOUNT_UNDER_REVIEW"
                      ],
                      "x-sendly-proposed-codes": [
                        "account_under_review"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "destination_not_authorized"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "DESTINATION_NOT_AUTHORIZED"
                          ]
                        },
                        "destinationCountry": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "destination_not_authorized",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "destination_not_authorized"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "registration_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SENDER_ID_NOT_REGISTERED"
                          ]
                        },
                        "countryCode": {
                          "type": "string"
                        },
                        "countryName": {
                          "type": "string"
                        },
                        "registrationUrl": {
                          "type": "string",
                          "description": "A dashboard path that starts the registration request."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "countryCode",
                        "countryName",
                        "registrationUrl"
                      ],
                      "title": "registration_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "registration_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The conversations API is not enabled for the account.\n- `not_found`: No draft with this id belongs to the key's workspace, the draft is no longer pending, its conversation is gone, or the key is a test key and the draft's conversation is not a sandbox conversation.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A draft that was already approved.",
                    "value": {
                      "error": "not_found",
                      "message": "Draft not found or not pending"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `conflict`: Another request approved or rejected the draft first.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "conflict"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "conflict",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "conflict"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `channel_not_supported`: The draft belongs to a WhatsApp conversation, which approval cannot send to yet.\n- `group_reply_not_supported`: The draft belongs to a group conversation, which approval cannot send to yet.\n- `undeliverable_number`: The contact is flagged as unable to receive texts.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "channel_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "channel_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "channel_not_supported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "group_reply_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "group_reply_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "group_reply_not_supported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "undeliverable_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "description": "Why the number cannot receive texts. Known values: `undeliverable_landline`, `undeliverable_invalid`, `undeliverable_non_sms`, `undeliverable_number`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "undeliverable_landline",
                            "undeliverable_invalid",
                            "undeliverable_non_sms",
                            "undeliverable_number"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "undeliverable_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "undeliverable_number"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The previous request's Idempotency-Key, reused with a different body.",
                    "value": {
                      "error": "idempotency_key_mismatch",
                      "message": "This idempotency key was already used with a different request body. Use a new key for different requests."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The approval or the send failed unexpectedly. When the send failed, the draft stays `approved`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/drafts/{id}/reject": {
      "post": {
        "operationId": "rejectDraft",
        "summary": "Reject a draft",
        "description": "Rejects a pending draft, so it is never sent. A test key can reject only a draft on a sandbox conversation.",
        "tags": [
          "Drafts"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "drafts",
          "method": "reject"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The draft's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "Why the draft was rejected.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RejectDraftRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- MessageDraft: The rejected draft.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageDraft"
                },
                "examples": {
                  "default": {
                    "summary": "A pending draft, rejected with a reason.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000009",
                      "userId": "00000000-0000-4000-8000-000000000003",
                      "organizationId": null,
                      "conversationId": "00000000-0000-4000-8000-000000000001",
                      "text": "Your Sendly code is 123456",
                      "mediaUrls": [],
                      "metadata": {},
                      "status": "rejected",
                      "source": "ai",
                      "createdBy": "00000000-0000-4000-8000-000000000004",
                      "reviewedBy": "00000000-0000-4000-8000-000000000003",
                      "reviewedAt": "2026-01-01T00:00:00.000Z",
                      "rejectionReason": "Too formal",
                      "messageId": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `reason` holds a NUL character.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No pending draft of the key's workspace has this id, the key is a test key and the draft's conversation is not a sandbox conversation, or the id is empty or holds a NUL character.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "A draft that was already rejected.",
                    "value": {
                      "error": "not_found",
                      "message": "Draft not found or not pending"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/account": {
      "get": {
        "operationId": "getEnterpriseAccount",
        "summary": "Get the enterprise account",
        "description": "Returns the enterprise account with every workspace it owns, each with its verification and credit balance. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise",
          "method": "getAccount"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseAccount: The enterprise account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseAccount"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: an account with two workspaces. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000100",
                      "maxWorkspaces": 25,
                      "workspaceCount": 2,
                      "workspaces": [
                        {
                          "id": "00000000-0000-4000-8000-000000000101",
                          "name": "Acme Dental",
                          "slug": "acme-dental",
                          "status": "active",
                          "suspendedAt": null,
                          "verificationStatus": "verified",
                          "rejectionReason": null,
                          "verificationType": "toll_free",
                          "tollFreeNumber": "+15555550123",
                          "creditBalance": 1200,
                          "monthlyMessageQuota": null,
                          "messagesThisMonth": 42
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000102",
                          "name": "Acme Ortho",
                          "slug": "acme-ortho",
                          "status": "suspended",
                          "suspendedAt": "2026-01-01T00:00:00.000Z",
                          "verificationStatus": "processing",
                          "rejectionReason": null,
                          "verificationType": "toll_free",
                          "tollFreeNumber": null,
                          "creditBalance": 0,
                          "monthlyMessageQuota": 5000,
                          "messagesThisMonth": 0
                        }
                      ],
                      "metadata": {
                        "webhookUrl": "https://example.com/hooks/sendly",
                        "webhookEvents": [
                          "workspace.created",
                          "credits.transferred"
                        ],
                        "autoTopUp": {
                          "enabled": false,
                          "threshold": 0,
                          "amount": 0,
                          "sourceWorkspaceId": null
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch enterprise account: The account could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch enterprise account"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch enterprise account",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/analytics/credits": {
      "get": {
        "operationId": "getEnterpriseCreditAnalytics",
        "summary": "Get credit analytics",
        "description": "Sums the credit balances of every team workspace the key's owner belongs to, in any role. The totals are all time: `period` is echoed but does not change them. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.analytics",
          "method": "credits"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "7d",
                "30d",
                "90d"
              ],
              "description": "Echoed in the answer. It does not change the totals."
            },
            "required": false,
            "name": "period",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseCreditAnalytics: The credit totals, all zero with no team workspaces.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseCreditAnalytics"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the credit totals of two workspaces. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "period": "30d",
                      "totalBalance": 4800,
                      "totalLifetime": 10000,
                      "totalUsed": 5200,
                      "workspaceCount": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch credit analytics: The totals could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch credit analytics"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch credit analytics",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/analytics/delivery": {
      "get": {
        "operationId": "getEnterpriseDeliveryAnalytics",
        "summary": "Get delivery analytics per workspace",
        "description": "Returns one row per team workspace the key's owner belongs to, in any role, with its all-time message counts and delivery rate. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.analytics",
          "method": "delivery"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- A bare array of rows, empty with no team workspaces.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnterpriseDeliveryAnalyticsItem"
                  }
                },
                "examples": {
                  "default": {
                    "summary": "Built from buildDeliveryAnalyticsItem: one workspace with messages, one without. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": [
                      {
                        "workspaceId": "00000000-0000-4000-8000-000000000101",
                        "workspaceName": "Acme Dental",
                        "totalMessages": 200,
                        "delivered": 187,
                        "deliveryRate": 93.5,
                        "name": "Acme Dental",
                        "sent": 200,
                        "failed": 9,
                        "rate": 94
                      },
                      {
                        "workspaceId": "00000000-0000-4000-8000-000000000102",
                        "workspaceName": "Acme Ortho",
                        "totalMessages": 0,
                        "delivered": 0,
                        "deliveryRate": 0,
                        "name": "Acme Ortho",
                        "sent": 0,
                        "failed": 0,
                        "rate": 0
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch delivery analytics: The counts could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch delivery analytics"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch delivery analytics",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/analytics/messages": {
      "get": {
        "operationId": "getEnterpriseMessageAnalytics",
        "summary": "Get daily message analytics",
        "description": "Counts the messages of one workspace, or of every team workspace the key's owner belongs to, per day. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.analytics",
          "method": "messages"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "7d",
                "30d",
                "90d"
              ],
              "description": "How many days back to count. Defaults to `30d`, which any other value means too."
            },
            "required": false,
            "name": "period",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only this workspace, which the key's owner must own. Without it, every team workspace the owner belongs to."
            },
            "required": false,
            "name": "workspaceId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseMessageAnalytics: The daily counts.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseMessageAnalytics"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: seven days, days with no messages as zeros. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "period": "7d",
                      "data": [
                        {
                          "date": "2025-12-26",
                          "sent": 0,
                          "delivered": 0,
                          "failed": 0
                        },
                        {
                          "date": "2025-12-27",
                          "sent": 12,
                          "delivered": 11,
                          "failed": 1
                        },
                        {
                          "date": "2025-12-28",
                          "sent": 30,
                          "delivered": 29,
                          "failed": 0
                        },
                        {
                          "date": "2025-12-29",
                          "sent": 0,
                          "delivered": 0,
                          "failed": 0
                        },
                        {
                          "date": "2025-12-30",
                          "sent": 8,
                          "delivered": 8,
                          "failed": 0
                        },
                        {
                          "date": "2025-12-31",
                          "sent": 25,
                          "delivered": 24,
                          "failed": 1
                        },
                        {
                          "date": "2026-01-01",
                          "sent": 5,
                          "delivered": 4,
                          "failed": 0
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- Access denied to this workspace: `workspaceId` names a workspace that does not exist, or that the key's owner does not own.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Access denied to this workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "access_denied"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Access denied to this workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "access_denied"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch message analytics: The counts could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch message analytics"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch message analytics",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/analytics/overview": {
      "get": {
        "operationId": "getEnterpriseAnalyticsOverview",
        "summary": "Get the analytics overview",
        "description": "Totals messages, delivery and credits across every team workspace the key's owner belongs to, in any role, all time. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.analytics",
          "method": "overview"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseAnalyticsOverview: The totals, all zero with no team workspaces.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseAnalyticsOverview"
                },
                "examples": {
                  "default": {
                    "summary": "Built from buildAnalyticsOverview: one active and one suspended workspace. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "totalWorkspaces": 2,
                      "totalMessages": 200,
                      "totalDelivered": 197,
                      "totalFailed": 2,
                      "deliveryRate": 98.5,
                      "totalCredits": 5000,
                      "deliveredMessages": 197,
                      "failedMessages": 2,
                      "totalCreditsUsed": 380,
                      "activeWorkspaces": 1,
                      "suspendedWorkspaces": 1,
                      "totalMessagesSent": 200,
                      "totalMessagesDelivered": 197,
                      "totalCreditsRemaining": 5000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key passed in the URL.",
                    "value": {
                      "error": "invalid_request",
                      "message": "API keys must not be passed in URL parameters. Use the Authorization header instead."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch analytics: The totals could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch analytics"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch analytics",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/billing/workspace-breakdown": {
      "get": {
        "operationId": "getEnterpriseBillingBreakdown",
        "summary": "Get the billing breakdown per workspace",
        "description": "Breaks the account's costs down by workspace for the period: credits used, purchased and transferred, messages, and each workspace's share of the fees. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-paged-by": [
          "page",
          "limit"
        ],
        "x-sendly-sdk": {
          "resource": "enterprise.billing",
          "method": "getBreakdown"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "7d",
                "30d",
                "90d"
              ],
              "description": "Defaults to `30d`."
            },
            "required": false,
            "name": "period",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "With `limit`, the page of `workspaces` to return, from 1."
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "With `page`, the page size. Without both, every workspace is returned."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseBillingBreakdown: The breakdown.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseBillingBreakdown"
                },
                "examples": {
                  "default": {
                    "summary": "Built from getWorkspaceBillingBreakdown: the default fees, one included workspace and one that pays its fee. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "period": "30d",
                      "includedWorkspaces": 1,
                      "summary": {
                        "platformFee": 29900,
                        "totalWorkspaceFees": 900,
                        "totalCreditsUsed": 500,
                        "totalCost": 31300
                      },
                      "workspaces": [
                        {
                          "id": "00000000-0000-4000-8000-000000000101",
                          "name": "Acme Dental",
                          "creditsUsed": 380,
                          "creditsPurchased": 1000,
                          "creditsTransferredIn": 0,
                          "creditsTransferredOut": 200,
                          "messagesSent": 190,
                          "messagesDelivered": 187,
                          "workspaceFee": 0,
                          "included": true,
                          "allocatedPlatformFee": 14950,
                          "totalCost": 15330
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000102",
                          "name": "Acme Ortho",
                          "creditsUsed": 120,
                          "creditsPurchased": 0,
                          "creditsTransferredIn": 200,
                          "creditsTransferredOut": 0,
                          "messagesSent": 60,
                          "messagesDelivered": 58,
                          "workspaceFee": 900,
                          "included": false,
                          "allocatedPlatformFee": 14950,
                          "totalCost": 15970
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- Invalid period. Must be 7d, 30d, or 90d: `period` is not `7d`, `30d` or `90d`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Invalid period. Must be 7d, 30d, or 90d"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Invalid period. Must be 7d, 30d, or 90d",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch billing breakdown: The breakdown could not be built.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch billing breakdown"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch billing breakdown",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/business-page/generate": {
      "post": {
        "operationId": "generateEnterpriseBusinessPage",
        "summary": "Generate a hosted business page",
        "description": "Creates a public business page at `/biz/{slug}`, which a toll-free verification can use as the business's website. Needs an enterprise master key; it does not check that the enterprise account is active.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise",
          "method": "generateBusinessPage"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "What the page shows.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateBusinessPageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- GeneratedBusinessPage: The page was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeneratedBusinessPage"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: a page for a workspace the key's owner owns. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "slug": "acme-dental-k3f9",
                      "url": "https://sendly.live/biz/acme-dental-k3f9",
                      "pageId": "00000000-0000-4000-8000-000000000104"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- businessName is required: `businessName` is missing or empty.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "businessName is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "businessName is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- Enterprise master key required: The key is not an enterprise master key.\n- `invalid_workspace`, `not_workspace_owner`: `organizationId` names a personal workspace (`invalid_workspace`), or one the key's owner does not own (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Enterprise master key required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "enterprise_required"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Enterprise master key required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "enterprise_required"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "Enterprise master key required"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: `organizationId` names no workspace, or is not a string.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Page generation failed: The page could not be created, as when `businessName` is not a string.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds the internal error's own message, which varies, and there is no `message`.",
                      "title": "Page generation failed",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/credits": {
      "get": {
        "operationId": "getEnterprisePoolCredits",
        "summary": "Get the shared credit pool",
        "description": "Returns the account's shared credit pool, which every workspace draws from when the account pools its credits. The first read creates an empty pool. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.credits",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- Pooled credits: The account pools its credits.\n- Per-workspace credits: Each workspace has its own credits, so there is no pool.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/EnterprisePoolCredits"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseCreditsNotPooled"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: an account that pools its credits. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "pooled": true,
                      "balance": 5000,
                      "lifetimeCredits": 10000,
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "not-pooled": {
                    "summary": "Built from the handler: an account whose workspaces each have their own credits. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "pooled": false,
                      "message": "Enterprise account uses per-workspace credits"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch pool credits: The pool could not be read or created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch pool credits"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch pool credits",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/credits/deposit": {
      "post": {
        "operationId": "depositEnterprisePoolCredits",
        "summary": "Deposit credits into the shared pool",
        "description": "Refuses every deposit with 403 `deposit_requires_payment`, whatever the body: credits reach the pool only through a payment in the enterprise dashboard, or an adjustment by Sendly support. The 200 below is not sent today. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.credits",
          "method": "deposit"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "Not read: every deposit is refused, with or without a body.",
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DepositPoolCreditsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterprisePoolDeposit: Not sent today: every deposit is refused with 403. It was the answer when a deposit added credits.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterprisePoolDeposit"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: 1,000 credits deposited into the pool. Not captured: a real deposit adds credits, and production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "balance": 6000,
                      "lifetimeCredits": 11000,
                      "deposited": 1000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `deposit_requires_payment`: Always, once the key is an enterprise master key: a deposit is never taken without a payment.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "deposit_requires_payment"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "deposit_requires_payment",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "deposit_requires_payment"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/settings/auto-top-up": {
      "get": {
        "operationId": "getEnterpriseAutoTopUp",
        "summary": "Get the auto top-up settings",
        "description": "Returns how workspaces are topped up from a source workspace when their balance runs low. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.settings",
          "method": "getAutoTopUp"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseAutoTopUp: The stored settings, or `enabled: false` with zeros and no source workspace when none were ever saved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseAutoTopUp"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the defaults, for an account that never saved settings. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "enabled": false,
                      "threshold": 0,
                      "amount": 0,
                      "sourceWorkspaceId": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch auto-top-up settings: The settings could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch auto-top-up settings"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch auto-top-up settings",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateEnterpriseAutoTopUp",
        "summary": "Update the auto top-up settings",
        "description": "Replaces the auto top-up settings as a whole: a field left out is reset. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.settings",
          "method": "updateAutoTopUp"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The new settings.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAutoTopUpRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseAutoTopUp: The settings were saved, and are returned as stored.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseAutoTopUp"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: top-ups of 2,000 credits from a source workspace. Not captured: it changes billing settings, and production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "enabled": true,
                      "threshold": 500,
                      "amount": 2000,
                      "sourceWorkspaceId": "00000000-0000-4000-8000-000000000101"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- Amount must be greater than 0: `enabled` is `true` and `amount` is missing or not above 0.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Amount must be greater than 0"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Amount must be greater than 0",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- You must own the source workspace: `enabled` is `true` and `sourceWorkspaceId` names a workspace that does not exist, or that the key's owner does not own.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "You must own the source workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "not_workspace_owner"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "You must own the source workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "not_workspace_owner"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to update auto-top-up settings: The settings could not be saved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to update auto-top-up settings"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to update auto-top-up settings",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/verification-document/upload": {
      "post": {
        "operationId": "uploadEnterpriseVerificationDocument",
        "summary": "Upload a verification document",
        "description": "Stores a business registration document for a toll-free verification. Send `multipart/form-data` with the file in the field `file` (a PNG, JPEG, GIF or WEBP image, or a PDF, up to 10 MB, sent with its content type), and optionally `verificationId` or `workspaceId`, which must be the key owner's: the document then becomes that verification's registration document, or that workspace's verification's. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise",
          "method": "uploadVerificationDocument"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- VerificationDocumentUpload: The document was stored.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationDocumentUpload"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: a PDF stored for a workspace's verification. The host is the storage bucket's public URL. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "url": "https://files.example.com/opt-in-documents/verification-docs/00000000-0000-4000-8000-000000000103/00000000-0000-4000-8000-000000000105.pdf",
                      "id": "upload_00000000000000000000000000000000"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_upload`: A file in a field other than `file`, a second file, or a malformed body such as one without a boundary.\n- No file provided: The body has no file in the field `file`, as when it is JSON rather than `multipart/form-data`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidUploadError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "No file provided"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "file_required"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "No file provided",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "file_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: `workspaceId` names a personal workspace (`invalid_workspace`), or one the key's owner does not own (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: `workspaceId` names no workspace.\n- `verification_not_found`: `verificationId` is not a string, names no verification, names one outside the `workspaceId` given, or names one the key's owner does not own.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "verification_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "verification_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "verification_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.\n- `file_too_large`: A file over 10 MB.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyTooLargeError"
                    },
                    {
                      "$ref": "#/components/schemas/FileTooLargeError"
                    }
                  ]
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.\n- `unsupported_media_type`: A file that is not a PNG, JPEG, GIF or WEBP image or a PDF (`Only images (PNG, JPG, GIF, WEBP) and PDFs are allowed`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyEncodingError"
                    },
                    {
                      "$ref": "#/components/schemas/UnsupportedMediaTypeError"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to upload file: The document could not be stored or recorded.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to upload file"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to upload file",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/webhooks": {
      "get": {
        "operationId": "getEnterpriseWebhook",
        "summary": "Get the enterprise webhook",
        "description": "Returns the account-wide webhook that receives events from every workspace. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.webhooks",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseAccountWebhook: The webhook, with `url` `null` when none is set.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseAccountWebhook"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: a webhook filtered to two event types. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "url": "https://example.com/hooks/sendly",
                      "events": [
                        "workspace.created",
                        "credits.transferred"
                      ],
                      "workspaces": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch webhook: The webhook could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch webhook"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch webhook",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "setEnterpriseWebhook",
        "summary": "Register the enterprise webhook",
        "description": "Sets the account-wide webhook URL and, optionally, its event and workspace filters. The first registration creates the signing secret and returns it once. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.webhooks",
          "method": "set"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The webhook.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetEnterpriseWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseAccountWebhookSet: The webhook was saved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseAccountWebhookSet"
                },
                "examples": {
                  "existing-secret": {
                    "summary": "Built from the handler: a later registration, which keeps the secret and leaves it out. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "url": "https://example.com/hooks/sendly-v2",
                      "events": [
                        "workspace.created",
                        "credits.transferred"
                      ],
                      "workspaces": null
                    }
                  },
                  "default": {
                    "summary": "Built from the handler: the account's first registration, which returns the new signing secret once. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "url": "https://example.com/hooks/sendly",
                      "events": [
                        "workspace.created",
                        "credits.transferred"
                      ],
                      "workspaces": null,
                      "signingSecret": "0000000000000000000000000000000000000000000000000000000000000001"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- url is required: `url` is missing or not a string.\n- Invalid URL: `url` is not a URL.\n- Webhook URL must use HTTPS: `url` does not start with `https://`.\n- Webhook URL points to a private or reserved network: `url` names localhost or a private, link-local or reserved address.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "url is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "url is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Invalid URL"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_url"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Invalid URL",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_url"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Webhook URL must use HTTPS"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_url"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Webhook URL must use HTTPS",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_url"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Webhook URL points to a private or reserved network"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_url"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Webhook URL points to a private or reserved network",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_url"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A body that is not valid JSON, answered by the body parser.",
                    "value": {
                      "message": "Expected double-quoted property name in JSON at position 44 (line 1 column 45)"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- Enterprise account not found: The enterprise account was removed after the key was checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Enterprise account not found"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "not_found"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "`error` holds a sentence, and there is no `message`.",
                  "title": "Enterprise account not found",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "not_found"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to register webhook: The webhook could not be saved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to register webhook"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to register webhook",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteEnterpriseWebhook",
        "summary": "Delete the enterprise webhook",
        "description": "Removes the webhook URL, so no more events are sent. The event and workspace filters and the signing secret are kept, and a later registration reuses them unless it sends new filters. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.webhooks",
          "method": "delete"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- The URL was removed, or there was none.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the webhook URL was removed. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "success": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- Enterprise account not found: The enterprise account was removed after the key was checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Enterprise account not found"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "not_found"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "`error` holds a sentence, and there is no `message`.",
                  "title": "Enterprise account not found",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "not_found"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to delete webhook: The webhook could not be removed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to delete webhook"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to delete webhook",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/webhooks/rotate-secret": {
      "post": {
        "operationId": "rotateEnterpriseWebhookSecret",
        "summary": "Rotate the enterprise webhook signing secret",
        "description": "Replaces the signing secret at once: deliveries are signed with the new one from now on, and the old one stops working. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.webhooks",
          "method": "rotateSecret"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseAccountWebhookSecret: The secret was replaced.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseAccountWebhookSecret"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the new secret, shown once. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "success": true,
                      "secret": "0000000000000000000000000000000000000000000000000000000000000001",
                      "rotated_at": "2026-01-01T00:00:00.000Z",
                      "message": "Webhook signing secret rotated. Save this secret - it won't be shown again."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- No webhook configured. Set a webhook URL first.: The account has no webhook URL.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "No webhook configured. Set a webhook URL first."
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "webhook_not_configured"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "No webhook configured. Set a webhook URL first.",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "webhook_not_configured"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- Enterprise account not found: The enterprise account was removed after the key was checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Enterprise account not found"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "not_found"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "`error` holds a sentence, and there is no `message`.",
                  "title": "Enterprise account not found",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "not_found"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to rotate webhook secret: The secret could not be replaced.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to rotate webhook secret"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to rotate webhook secret",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/webhooks/test": {
      "post": {
        "operationId": "testEnterpriseWebhook",
        "summary": "Send a test event to the enterprise webhook",
        "description": "POSTs a `webhook.test` event to the webhook URL, waiting up to 10 seconds, and reports how the endpoint answered. The test event is not signed. Needs an enterprise master key on an active enterprise account; any other key answers 403.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.webhooks",
          "method": "test"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseAccountWebhookTest: The test was sent. A 200 even when the endpoint failed or could not be reached: read `success`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseAccountWebhookTest"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the endpoint answered 200. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "success": true,
                      "statusCode": 200,
                      "statusText": "OK"
                    }
                  },
                  "timed-out": {
                    "summary": "Built from the handler: the endpoint did not answer within 10 seconds. Not captured: production answers 403 to any key but an enterprise master key.",
                    "value": {
                      "success": false,
                      "error": "Request timed out (10s)"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- No webhook URL configured: The account has no webhook URL.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "No webhook URL configured"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "webhook_not_configured"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "`error` holds a sentence, and there is no `message`.",
                  "title": "No webhook URL configured",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "webhook_not_configured"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to test webhook: The test could not be sent.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to test webhook"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to test webhook",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces": {
      "get": {
        "operationId": "listEnterpriseWorkspaces",
        "summary": "List workspaces",
        "description": "Lists the workspaces the enterprise key's owner owns, with their verification, credits, keys, 30-day message counts and tags, plus totals over all of them. With `compact=true`, returns every workspace's id, name and balance instead, ignoring the filters and paging.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "page-number",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "list"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "maximum": 100,
              "description": "Page size, up to 100. Defaults to 50; a larger value gives 100."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "The page, starting at 1. Defaults to 1."
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only workspaces whose name contains this, ignoring case."
            },
            "required": false,
            "name": "search",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only workspaces with this status. `all`, the default, keeps all."
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only workspaces whose verification has this status, stored or as returned. `unverified` keeps those with none; `all`, the default, keeps all."
            },
            "required": false,
            "name": "verification",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "created_desc",
                "created_asc",
                "name_asc",
                "name_desc",
                "credits_desc",
                "credits_asc"
              ],
              "description": "The order. Defaults to `created_desc`, newest first."
            },
            "required": false,
            "name": "sort",
            "in": "query"
          },
          {
            "schema": {
              "type": "boolean",
              "description": "`true` returns the compact list. Any other value is ignored."
            },
            "required": false,
            "name": "compact",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated tag ids: only workspaces with at least one of them."
            },
            "required": false,
            "name": "tags",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Workspaces, a page: A page of workspaces.\n- Workspaces, compact: `compact` is `true`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/EnterpriseWorkspaceList"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseWorkspaceCompactList"
                    }
                  ]
                },
                "examples": {
                  "compact": {
                    "summary": "The compact list: built from buildEnterpriseWorkspaceResponse with compact=true.",
                    "value": {
                      "workspaces": [
                        {
                          "id": "00000000-0000-4000-8000-000000000011",
                          "name": "Bright Smiles Dental",
                          "creditBalance": 0
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000010",
                          "name": "Acme Clinics",
                          "creditBalance": 1500
                        }
                      ],
                      "summary": {
                        "totalCredits": 1500,
                        "pendingVerifications": [
                          {
                            "id": "00000000-0000-4000-8000-000000000011",
                            "name": "Bright Smiles Dental"
                          }
                        ],
                        "verificationBreakdown": {
                          "verified": 1,
                          "pending": 1,
                          "submitted": 0,
                          "rejected": 0,
                          "unverified": 0
                        }
                      },
                      "maxWorkspaces": 25,
                      "workspacesUsed": 2
                    }
                  },
                  "default": {
                    "summary": "An enterprise master key listed its two workspaces: built from buildEnterpriseWorkspaceResponse, since a test key is never an enterprise master key.",
                    "value": {
                      "workspaces": [
                        {
                          "id": "00000000-0000-4000-8000-000000000011",
                          "name": "Bright Smiles Dental",
                          "slug": "bright-smiles-dental",
                          "status": "active",
                          "suspendedAt": null,
                          "suspendReason": null,
                          "verificationStatus": "pending",
                          "rejectionReason": null,
                          "verificationType": "toll_free",
                          "tollFreeNumber": null,
                          "creditBalance": 0,
                          "keyCount": 1,
                          "messages30d": 0,
                          "delivered30d": 0,
                          "failed30d": 0,
                          "monthlyMessageQuota": null,
                          "messagesThisMonth": 0,
                          "quotaResetAt": null,
                          "createdAt": "2026-01-08T00:00:00.000Z",
                          "tags": [
                            {
                              "id": "00000000-0000-4000-8000-000000000030",
                              "enterpriseAccountId": "00000000-0000-4000-8000-000000000031",
                              "name": "dental",
                              "color": "#6366f1",
                              "createdAt": "2026-01-01T00:00:00.000Z"
                            }
                          ]
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000010",
                          "name": "Acme Clinics",
                          "slug": "acme-clinics",
                          "status": "active",
                          "suspendedAt": null,
                          "suspendReason": null,
                          "verificationStatus": "verified",
                          "rejectionReason": null,
                          "verificationType": "toll_free",
                          "tollFreeNumber": "+15555550100",
                          "creditBalance": 1500,
                          "keyCount": 1,
                          "messages30d": 120,
                          "delivered30d": 118,
                          "failed30d": 2,
                          "monthlyMessageQuota": null,
                          "messagesThisMonth": 40,
                          "quotaResetAt": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "tags": []
                        }
                      ],
                      "pagination": {
                        "total": 2,
                        "limit": 50,
                        "page": 1,
                        "totalPages": 1,
                        "hasMore": false
                      },
                      "summary": {
                        "totalCredits": 1500,
                        "pendingVerifications": [
                          {
                            "id": "00000000-0000-4000-8000-000000000011",
                            "name": "Bright Smiles Dental"
                          }
                        ],
                        "verificationBreakdown": {
                          "verified": 1,
                          "pending": 1,
                          "submitted": 0,
                          "rejected": 0,
                          "unverified": 0
                        }
                      },
                      "maxWorkspaces": 25,
                      "workspacesUsed": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "unknown-key": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch workspaces: The workspaces could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch workspaces"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch workspaces",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createEnterpriseWorkspace",
        "summary": "Create a workspace",
        "description": "Creates an empty workspace owned by the enterprise key's owner, with a zero credit balance, and updates the account's per-workspace billing.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "create"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The workspace to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The workspace's name. Must not be blank."
                  },
                  "description": {
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- EnterpriseWorkspaceCreated: The workspace was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceCreated"
                },
                "examples": {
                  "default": {
                    "summary": "A workspace was created: built from the handler, since creating one is provisioning and changes billing.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000010",
                      "name": "Acme Clinics",
                      "slug": "acme-clinics",
                      "createdAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- name is required: `name` is missing, not a string, or blank.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "name is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "name is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A body that is not valid JSON, answered by the body parser.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- Workspace limit reached: The account already has as many workspaces as it may have.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Workspace limit reached"
                          ]
                        },
                        "currentCount": {
                          "type": "integer"
                        },
                        "maxWorkspaces": {
                          "type": "integer"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "workspace_limit_reached"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error",
                        "currentCount",
                        "maxWorkspaces"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Workspace limit reached",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "workspace_limit_reached"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to create a workspace.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  },
                  "limit-reached": {
                    "summary": "The account already has as many workspaces as it may have: built from the handler.",
                    "value": {
                      "error": "Workspace limit reached",
                      "currentCount": 25,
                      "maxWorkspaces": 25
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- A workspace with a similar name already exists: Any workspace on Sendly, not only this account's, already has the slug the name makes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "A workspace with a similar name already exists"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "workspace_name_taken"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "`error` holds a sentence, and there is no `message`.",
                  "title": "A workspace with a similar name already exists",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "workspace_name_taken"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to create workspace: The workspace could not be created, or `description` is not a string.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to create workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to create workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/provision": {
      "post": {
        "operationId": "provisionEnterpriseWorkspace",
        "summary": "Provision a workspace",
        "description": "Creates a workspace and sets it up in one call: a verification (inherited or new, with a sending profile and a bought toll-free number where that applies, which costs money), hosted opt-in, legal and business pages, credits, an API key and the enterprise webhook. Each optional step that fails is reported in its own field, and the workspace is still created. Sends a `workspace.created` enterprise webhook.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise",
          "method": "provision"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The workspace to provision.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "The workspace's name. Its slug must not match an existing workspace's."
                      },
                      "inheritWithNewNumber": {
                        "type": "boolean",
                        "description": "With `sourceWorkspaceId`, copy the business details and buy a new toll-free number instead of sharing the source's."
                      },
                      "verificationOverrides": {
                        "type": "object",
                        "properties": {
                          "businessName": {
                            "type": "string"
                          },
                          "website": {
                            "type": "string"
                          },
                          "doingBusinessAs": {
                            "type": "string"
                          },
                          "entityType": {
                            "type": "string"
                          },
                          "brn": {
                            "type": "string",
                            "description": "For a US registration, an EIN as `12-3456789`."
                          },
                          "brnType": {
                            "type": "string"
                          },
                          "brnCountry": {
                            "type": "string"
                          },
                          "useCase": {
                            "type": "string"
                          },
                          "useCaseSummary": {
                            "type": "string"
                          },
                          "sampleMessages": {
                            "type": "string"
                          },
                          "monthlyVolume": {
                            "type": "string"
                          },
                          "additionalInformation": {
                            "type": "string"
                          },
                          "contact": {
                            "type": "object",
                            "properties": {
                              "firstName": {
                                "type": "string"
                              },
                              "lastName": {
                                "type": "string"
                              },
                              "email": {
                                "type": "string"
                              },
                              "phone": {
                                "type": "string",
                                "description": "In E.164 format."
                              }
                            }
                          },
                          "address": {
                            "type": "object",
                            "properties": {
                              "addr1": {
                                "type": "string"
                              },
                              "addr2": {
                                "type": "string"
                              },
                              "city": {
                                "type": "string"
                              },
                              "state": {
                                "type": "string"
                              },
                              "zip": {
                                "type": "string"
                              },
                              "country": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "description": "With `inheritWithNewNumber`, fields that replace the copied ones."
                      },
                      "creditAmount": {
                        "anyOf": [
                          {
                            "type": "integer"
                          },
                          {
                            "type": "string"
                          }
                        ],
                        "description": "Credits to move in from `creditSourceWorkspaceId`. A string is read as a number."
                      },
                      "creditSourceWorkspaceId": {
                        "type": "string"
                      },
                      "keyName": {
                        "type": "string",
                        "description": "Create an API key with this name."
                      },
                      "keyType": {
                        "type": "string",
                        "enum": [
                          "test",
                          "live"
                        ],
                        "description": "The new key's type. Anything but `live` makes a test key."
                      },
                      "webhookUrl": {
                        "type": "string",
                        "description": "An `https://` URL saved as the enterprise account's webhook. Checked only after everything else is provisioned."
                      },
                      "generateOptInPage": {
                        "type": "boolean",
                        "description": "Defaults to `true`: creates a hosted opt-in page and privacy and terms pages."
                      },
                      "generateBusinessPage": {
                        "type": "boolean",
                        "description": "With `verification` and no `website`, creates a hosted business page to use as the website."
                      },
                      "sourceWorkspaceId": {
                        "type": "string",
                        "description": "Inherit the verification of this workspace the key's owner owns. Wins over `verification`."
                      }
                    },
                    "required": [
                      "name",
                      "sourceWorkspaceId"
                    ],
                    "title": "Inherit a verification"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "The workspace's name. Its slug must not match an existing workspace's."
                      },
                      "inheritWithNewNumber": {
                        "type": "boolean",
                        "description": "With `sourceWorkspaceId`, copy the business details and buy a new toll-free number instead of sharing the source's."
                      },
                      "verificationOverrides": {
                        "type": "object",
                        "properties": {
                          "businessName": {
                            "type": "string"
                          },
                          "website": {
                            "type": "string"
                          },
                          "doingBusinessAs": {
                            "type": "string"
                          },
                          "entityType": {
                            "type": "string"
                          },
                          "brn": {
                            "type": "string",
                            "description": "For a US registration, an EIN as `12-3456789`."
                          },
                          "brnType": {
                            "type": "string"
                          },
                          "brnCountry": {
                            "type": "string"
                          },
                          "useCase": {
                            "type": "string"
                          },
                          "useCaseSummary": {
                            "type": "string"
                          },
                          "sampleMessages": {
                            "type": "string"
                          },
                          "monthlyVolume": {
                            "type": "string"
                          },
                          "additionalInformation": {
                            "type": "string"
                          },
                          "contact": {
                            "type": "object",
                            "properties": {
                              "firstName": {
                                "type": "string"
                              },
                              "lastName": {
                                "type": "string"
                              },
                              "email": {
                                "type": "string"
                              },
                              "phone": {
                                "type": "string",
                                "description": "In E.164 format."
                              }
                            }
                          },
                          "address": {
                            "type": "object",
                            "properties": {
                              "addr1": {
                                "type": "string"
                              },
                              "addr2": {
                                "type": "string"
                              },
                              "city": {
                                "type": "string"
                              },
                              "state": {
                                "type": "string"
                              },
                              "zip": {
                                "type": "string"
                              },
                              "country": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "description": "With `inheritWithNewNumber`, fields that replace the copied ones."
                      },
                      "creditAmount": {
                        "anyOf": [
                          {
                            "type": "integer"
                          },
                          {
                            "type": "string"
                          }
                        ],
                        "description": "Credits to move in from `creditSourceWorkspaceId`. A string is read as a number."
                      },
                      "creditSourceWorkspaceId": {
                        "type": "string"
                      },
                      "keyName": {
                        "type": "string",
                        "description": "Create an API key with this name."
                      },
                      "keyType": {
                        "type": "string",
                        "enum": [
                          "test",
                          "live"
                        ],
                        "description": "The new key's type. Anything but `live` makes a test key."
                      },
                      "webhookUrl": {
                        "type": "string",
                        "description": "An `https://` URL saved as the enterprise account's webhook. Checked only after everything else is provisioned."
                      },
                      "generateOptInPage": {
                        "type": "boolean",
                        "description": "Defaults to `true`: creates a hosted opt-in page and privacy and terms pages."
                      },
                      "generateBusinessPage": {
                        "type": "boolean",
                        "description": "With `verification` and no `website`, creates a hosted business page to use as the website."
                      },
                      "verification": {
                        "type": "object",
                        "properties": {
                          "businessName": {
                            "type": "string"
                          },
                          "doingBusinessAs": {
                            "type": "string"
                          },
                          "website": {
                            "type": "string",
                            "description": "Required unless `generateBusinessPage` is `true`."
                          },
                          "address": {
                            "type": "object",
                            "properties": {
                              "street": {
                                "type": "string"
                              },
                              "address1": {
                                "type": "string",
                                "description": "Read when `street` is absent."
                              },
                              "address2": {
                                "type": "string"
                              },
                              "city": {
                                "type": "string"
                              },
                              "state": {
                                "type": "string",
                                "description": "A state name or its two-letter code."
                              },
                              "zip": {
                                "type": "string"
                              },
                              "country": {
                                "type": "string",
                                "description": "An ISO country code. Defaults to `US`."
                              }
                            },
                            "required": [
                              "city",
                              "state",
                              "zip"
                            ],
                            "description": "The business address. `street` or `address1` is required."
                          },
                          "contact": {
                            "type": "object",
                            "properties": {
                              "firstName": {
                                "type": "string"
                              },
                              "lastName": {
                                "type": "string"
                              },
                              "email": {
                                "type": "string"
                              },
                              "phone": {
                                "type": "string",
                                "description": "In E.164 format."
                              }
                            },
                            "required": [
                              "firstName",
                              "lastName",
                              "email",
                              "phone"
                            ]
                          },
                          "brn": {
                            "type": "string",
                            "description": "For a US registration, an EIN as `12-3456789`."
                          },
                          "brnType": {
                            "type": "string"
                          },
                          "brnCountry": {
                            "type": "string",
                            "description": "Defaults to `US`."
                          },
                          "entityType": {
                            "type": "string"
                          },
                          "useCase": {
                            "type": "string",
                            "enum": [
                              "2FA",
                              "App Notifications",
                              "Appointments",
                              "Billing",
                              "Booking Confirmations",
                              "Chatbot",
                              "Conversational / Alerts",
                              "Courier Services & Deliveries",
                              "Emergency Alerts",
                              "Events & Planning",
                              "Financial Services",
                              "Fraud Alerts",
                              "General Marketing",
                              "General School Updates",
                              "Healthcare Alerts",
                              "HR / Staffing",
                              "Insurance Services",
                              "Order Notifications",
                              "Public Works",
                              "Real Estate Services",
                              "Rewards Program",
                              "System Alerts",
                              "Voting Reminders"
                            ]
                          },
                          "useCaseSummary": {
                            "type": "string"
                          },
                          "sampleMessages": {
                            "type": "string"
                          },
                          "optInWorkflow": {
                            "type": "string"
                          },
                          "optInImageUrls": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            ]
                          },
                          "monthlyVolume": {
                            "type": "string"
                          },
                          "additionalInformation": {
                            "type": "string"
                          },
                          "ageGatedContent": {
                            "type": "boolean"
                          },
                          "privacyUrl": {
                            "type": "string"
                          },
                          "termsUrl": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "businessName",
                          "address",
                          "contact",
                          "brn",
                          "useCase",
                          "useCaseSummary",
                          "sampleMessages"
                        ],
                        "description": "The business details for a new, independent verification."
                      }
                    },
                    "required": [
                      "name",
                      "verification"
                    ],
                    "title": "New verification"
                  }
                ],
                "description": "`sourceWorkspaceId` (inherit) or `verification` (independent) is required."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- EnterpriseProvisionResult: The workspace was provisioned.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseProvisionResult"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: a workspace that shares a verified workspace's verification, with credits and a test key.",
                    "value": {
                      "workspace": {
                        "id": "00000000-0000-4000-8000-000000000101",
                        "name": "Acme Dental",
                        "slug": "acme-dental"
                      },
                      "verification": {
                        "id": "00000000-0000-4000-8000-000000000103",
                        "status": "verified",
                        "type": "toll_free",
                        "tollFreeNumber": "+15555550142",
                        "inherited": true
                      },
                      "optInPage": {
                        "id": "page_placeholder1",
                        "slug": "acme-dental-a1b2",
                        "url": "https://sendly.live/opt-in/acme-dental-a1b2"
                      },
                      "legalPages": {
                        "privacyUrl": "https://sendly.live/legal/acme-dental-c3d4-privacy",
                        "termsUrl": "https://sendly.live/legal/acme-dental-c3d4-terms",
                        "privacyPageId": "page_placeholder2",
                        "termsPageId": "page_placeholder3"
                      },
                      "credits": {
                        "transferred": 500,
                        "balance": 500
                      },
                      "key": {
                        "id": "key_placeholder1",
                        "name": "Acme Dental production",
                        "key": "sk_test_v1_placeholder",
                        "keyPrefix": "sk_test_v1_placeholder",
                        "type": "test"
                      },
                      "apiBaseUrl": "https://sendly.live",
                      "dashboardUrl": "https://sendly.live/enterprise/workspaces/00000000-0000-4000-8000-000000000101"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- name is required: `name` is missing or not a string.\n- Either sourceWorkspaceId (inherit) or verification (independent) is required: Neither `sourceWorkspaceId` nor `verification` was sent.\n- Missing required verification fields: `verification` lacks a required field. The new workspace is deleted.\n- Invalid useCase: `verification.useCase` is not a known use case. The new workspace is deleted.\n- Invalid EIN format. Expected: XX-XXXXXXX (e.g., 12-3456789): A US `brn` is not an EIN. The new workspace is deleted.\n- Source workspace has no active verification: The source workspace has no verification with a sending profile. The new workspace is kept.\n- Webhook URL must use HTTPS: `webhookUrl` is not `https://`. Checked last: the workspace and everything else asked for were already provisioned and are kept.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "name is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "name is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Either sourceWorkspaceId (inherit) or verification (independent) is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Either sourceWorkspaceId (inherit) or verification (independent) is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Missing required verification fields"
                          ]
                        },
                        "missingFields": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error",
                        "missingFields"
                      ],
                      "title": "Missing required verification fields",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` names the value and lists every valid one.",
                      "title": "Invalid useCase",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Invalid EIN format. Expected: XX-XXXXXXX (e.g., 12-3456789)"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Invalid EIN format. Expected: XX-XXXXXXX (e.g., 12-3456789)",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Source workspace has no active verification"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "not_verified"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Source workspace has no active verification",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "not_verified"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Webhook URL must use HTTPS"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_url"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Webhook URL must use HTTPS",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_url"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- Workspace limit reached: The enterprise account has its most workspaces already.\n- You must own the source workspace: The key's owner does not own `sourceWorkspaceId`. The new workspace is kept.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Workspace limit reached"
                          ]
                        },
                        "currentCount": {
                          "type": "integer"
                        },
                        "maxWorkspaces": {
                          "type": "integer"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "workspace_limit_reached"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error",
                        "currentCount",
                        "maxWorkspaces"
                      ],
                      "title": "Workspace limit reached",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "workspace_limit_reached"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "You must own the source workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "not_workspace_owner"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "You must own the source workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "not_workspace_owner"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- A workspace with a similar name already exists: A workspace with the same slug exists.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "A workspace with a similar name already exists"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "workspace_name_taken"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "A workspace with a similar name already exists",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "workspace_name_taken"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `provision_rate_limit`: The account has already made 120 provisioning requests this minute, or 1,000 this hour.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "$ref": "#/components/schemas/ProvisionRateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Sending profile not created: A new verification's sending profile could not be created. The new workspace is deleted.\n- Failed to provision workspace: Provisioning failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` is the sentence the profile service gave, or `Failed to create messaging profile`.",
                      "title": "Sending profile not created",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to provision workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to provision workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `provisioning_paused`: Provisioning is paused after repeated upstream failures, for every enterprise or for this one.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "provisioning_paused"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "circuitBreaker": {
                      "type": "object",
                      "properties": {
                        "failures": {
                          "type": "integer"
                        },
                        "isOpen": {
                          "type": "boolean"
                        },
                        "openUntil": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "When provisioning resumes. ISO 8601, in UTC."
                        }
                      },
                      "required": [
                        "failures",
                        "isOpen",
                        "openUntil"
                      ],
                      "description": "Present when every enterprise's provisioning is paused."
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "provisioning_paused",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "provisioning_paused"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/provision/async": {
      "post": {
        "operationId": "provisionEnterpriseWorkspaceAsync",
        "summary": "Provision a workspace in the background",
        "description": "Hands the workspace to a background worker, which calls `POST /api/v1/enterprise/workspaces/provision` with your key, retries it, and posts the result to `callbackUrl`. Answers 202 with whatever the worker answered, a refusal included.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The workspace to provision.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "workspace": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "The workspace's name. Its slug must not match an existing workspace's."
                          },
                          "inheritWithNewNumber": {
                            "type": "boolean",
                            "description": "With `sourceWorkspaceId`, copy the business details and buy a new toll-free number instead of sharing the source's."
                          },
                          "verificationOverrides": {
                            "type": "object",
                            "properties": {
                              "businessName": {
                                "type": "string"
                              },
                              "website": {
                                "type": "string"
                              },
                              "doingBusinessAs": {
                                "type": "string"
                              },
                              "entityType": {
                                "type": "string"
                              },
                              "brn": {
                                "type": "string",
                                "description": "For a US registration, an EIN as `12-3456789`."
                              },
                              "brnType": {
                                "type": "string"
                              },
                              "brnCountry": {
                                "type": "string"
                              },
                              "useCase": {
                                "type": "string"
                              },
                              "useCaseSummary": {
                                "type": "string"
                              },
                              "sampleMessages": {
                                "type": "string"
                              },
                              "monthlyVolume": {
                                "type": "string"
                              },
                              "additionalInformation": {
                                "type": "string"
                              },
                              "contact": {
                                "type": "object",
                                "properties": {
                                  "firstName": {
                                    "type": "string"
                                  },
                                  "lastName": {
                                    "type": "string"
                                  },
                                  "email": {
                                    "type": "string"
                                  },
                                  "phone": {
                                    "type": "string",
                                    "description": "In E.164 format."
                                  }
                                }
                              },
                              "address": {
                                "type": "object",
                                "properties": {
                                  "addr1": {
                                    "type": "string"
                                  },
                                  "addr2": {
                                    "type": "string"
                                  },
                                  "city": {
                                    "type": "string"
                                  },
                                  "state": {
                                    "type": "string"
                                  },
                                  "zip": {
                                    "type": "string"
                                  },
                                  "country": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "description": "With `inheritWithNewNumber`, fields that replace the copied ones."
                          },
                          "creditAmount": {
                            "anyOf": [
                              {
                                "type": "integer"
                              },
                              {
                                "type": "string"
                              }
                            ],
                            "description": "Credits to move in from `creditSourceWorkspaceId`. A string is read as a number."
                          },
                          "creditSourceWorkspaceId": {
                            "type": "string"
                          },
                          "keyName": {
                            "type": "string",
                            "description": "Create an API key with this name."
                          },
                          "keyType": {
                            "type": "string",
                            "enum": [
                              "test",
                              "live"
                            ],
                            "description": "The new key's type. Anything but `live` makes a test key."
                          },
                          "webhookUrl": {
                            "type": "string",
                            "description": "An `https://` URL saved as the enterprise account's webhook. Checked only after everything else is provisioned."
                          },
                          "generateOptInPage": {
                            "type": "boolean",
                            "description": "Defaults to `true`: creates a hosted opt-in page and privacy and terms pages."
                          },
                          "generateBusinessPage": {
                            "type": "boolean",
                            "description": "With `verification` and no `website`, creates a hosted business page to use as the website."
                          },
                          "sourceWorkspaceId": {
                            "type": "string",
                            "description": "Inherit the verification of this workspace the key's owner owns. Wins over `verification`."
                          }
                        },
                        "required": [
                          "name",
                          "sourceWorkspaceId"
                        ],
                        "title": "Inherit a verification"
                      },
                      {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "The workspace's name. Its slug must not match an existing workspace's."
                          },
                          "inheritWithNewNumber": {
                            "type": "boolean",
                            "description": "With `sourceWorkspaceId`, copy the business details and buy a new toll-free number instead of sharing the source's."
                          },
                          "verificationOverrides": {
                            "type": "object",
                            "properties": {
                              "businessName": {
                                "type": "string"
                              },
                              "website": {
                                "type": "string"
                              },
                              "doingBusinessAs": {
                                "type": "string"
                              },
                              "entityType": {
                                "type": "string"
                              },
                              "brn": {
                                "type": "string",
                                "description": "For a US registration, an EIN as `12-3456789`."
                              },
                              "brnType": {
                                "type": "string"
                              },
                              "brnCountry": {
                                "type": "string"
                              },
                              "useCase": {
                                "type": "string"
                              },
                              "useCaseSummary": {
                                "type": "string"
                              },
                              "sampleMessages": {
                                "type": "string"
                              },
                              "monthlyVolume": {
                                "type": "string"
                              },
                              "additionalInformation": {
                                "type": "string"
                              },
                              "contact": {
                                "type": "object",
                                "properties": {
                                  "firstName": {
                                    "type": "string"
                                  },
                                  "lastName": {
                                    "type": "string"
                                  },
                                  "email": {
                                    "type": "string"
                                  },
                                  "phone": {
                                    "type": "string",
                                    "description": "In E.164 format."
                                  }
                                }
                              },
                              "address": {
                                "type": "object",
                                "properties": {
                                  "addr1": {
                                    "type": "string"
                                  },
                                  "addr2": {
                                    "type": "string"
                                  },
                                  "city": {
                                    "type": "string"
                                  },
                                  "state": {
                                    "type": "string"
                                  },
                                  "zip": {
                                    "type": "string"
                                  },
                                  "country": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "description": "With `inheritWithNewNumber`, fields that replace the copied ones."
                          },
                          "creditAmount": {
                            "anyOf": [
                              {
                                "type": "integer"
                              },
                              {
                                "type": "string"
                              }
                            ],
                            "description": "Credits to move in from `creditSourceWorkspaceId`. A string is read as a number."
                          },
                          "creditSourceWorkspaceId": {
                            "type": "string"
                          },
                          "keyName": {
                            "type": "string",
                            "description": "Create an API key with this name."
                          },
                          "keyType": {
                            "type": "string",
                            "enum": [
                              "test",
                              "live"
                            ],
                            "description": "The new key's type. Anything but `live` makes a test key."
                          },
                          "webhookUrl": {
                            "type": "string",
                            "description": "An `https://` URL saved as the enterprise account's webhook. Checked only after everything else is provisioned."
                          },
                          "generateOptInPage": {
                            "type": "boolean",
                            "description": "Defaults to `true`: creates a hosted opt-in page and privacy and terms pages."
                          },
                          "generateBusinessPage": {
                            "type": "boolean",
                            "description": "With `verification` and no `website`, creates a hosted business page to use as the website."
                          },
                          "verification": {
                            "type": "object",
                            "properties": {
                              "businessName": {
                                "type": "string"
                              },
                              "doingBusinessAs": {
                                "type": "string"
                              },
                              "website": {
                                "type": "string",
                                "description": "Required unless `generateBusinessPage` is `true`."
                              },
                              "address": {
                                "type": "object",
                                "properties": {
                                  "street": {
                                    "type": "string"
                                  },
                                  "address1": {
                                    "type": "string",
                                    "description": "Read when `street` is absent."
                                  },
                                  "address2": {
                                    "type": "string"
                                  },
                                  "city": {
                                    "type": "string"
                                  },
                                  "state": {
                                    "type": "string",
                                    "description": "A state name or its two-letter code."
                                  },
                                  "zip": {
                                    "type": "string"
                                  },
                                  "country": {
                                    "type": "string",
                                    "description": "An ISO country code. Defaults to `US`."
                                  }
                                },
                                "required": [
                                  "city",
                                  "state",
                                  "zip"
                                ],
                                "description": "The business address. `street` or `address1` is required."
                              },
                              "contact": {
                                "type": "object",
                                "properties": {
                                  "firstName": {
                                    "type": "string"
                                  },
                                  "lastName": {
                                    "type": "string"
                                  },
                                  "email": {
                                    "type": "string"
                                  },
                                  "phone": {
                                    "type": "string",
                                    "description": "In E.164 format."
                                  }
                                },
                                "required": [
                                  "firstName",
                                  "lastName",
                                  "email",
                                  "phone"
                                ]
                              },
                              "brn": {
                                "type": "string",
                                "description": "For a US registration, an EIN as `12-3456789`."
                              },
                              "brnType": {
                                "type": "string"
                              },
                              "brnCountry": {
                                "type": "string",
                                "description": "Defaults to `US`."
                              },
                              "entityType": {
                                "type": "string"
                              },
                              "useCase": {
                                "type": "string",
                                "enum": [
                                  "2FA",
                                  "App Notifications",
                                  "Appointments",
                                  "Billing",
                                  "Booking Confirmations",
                                  "Chatbot",
                                  "Conversational / Alerts",
                                  "Courier Services & Deliveries",
                                  "Emergency Alerts",
                                  "Events & Planning",
                                  "Financial Services",
                                  "Fraud Alerts",
                                  "General Marketing",
                                  "General School Updates",
                                  "Healthcare Alerts",
                                  "HR / Staffing",
                                  "Insurance Services",
                                  "Order Notifications",
                                  "Public Works",
                                  "Real Estate Services",
                                  "Rewards Program",
                                  "System Alerts",
                                  "Voting Reminders"
                                ]
                              },
                              "useCaseSummary": {
                                "type": "string"
                              },
                              "sampleMessages": {
                                "type": "string"
                              },
                              "optInWorkflow": {
                                "type": "string"
                              },
                              "optInImageUrls": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                ]
                              },
                              "monthlyVolume": {
                                "type": "string"
                              },
                              "additionalInformation": {
                                "type": "string"
                              },
                              "ageGatedContent": {
                                "type": "boolean"
                              },
                              "privacyUrl": {
                                "type": "string"
                              },
                              "termsUrl": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "businessName",
                              "address",
                              "contact",
                              "brn",
                              "useCase",
                              "useCaseSummary",
                              "sampleMessages"
                            ],
                            "description": "The business details for a new, independent verification."
                          }
                        },
                        "required": [
                          "name",
                          "verification"
                        ],
                        "title": "New verification"
                      }
                    ],
                    "description": "The workspace, as `POST /api/v1/enterprise/workspaces/provision` takes it."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "description": "An `https://` URL on a public network that gets the result."
                  }
                },
                "required": [
                  "workspace"
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted.\n\n- Provisioning started: The worker started the run.\n- Refused by the background worker: The worker refused the run, such as for an unusable `callbackUrl`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "instanceId": {
                          "type": "string",
                          "description": "The provisioning run's id. Poll `GET /provision/status/{instanceId}` with it."
                        },
                        "status": {
                          "type": "object",
                          "properties": {
                            "status": {
                              "type": "string",
                              "description": "Where the provisioning run is. Known values: `queued`, `running`, `paused`, `errored`, `terminated`, `complete`, `waiting`, `waitingForPause`, `unknown`. More can be added at any time, so treat an unknown value as valid.",
                              "x-sendly-extensible-enum": [
                                "queued",
                                "running",
                                "paused",
                                "errored",
                                "terminated",
                                "complete",
                                "waiting",
                                "waitingForPause",
                                "unknown"
                              ]
                            },
                            "error": {
                              "description": "Why the run failed."
                            },
                            "output": {
                              "description": "When the run is complete, what `POST /api/v1/enterprise/workspaces/provision` answered, including any new API key in full."
                            }
                          },
                          "required": [
                            "status"
                          ],
                          "description": "The provisioning run's state, as the background worker reports it."
                        }
                      },
                      "required": [
                        "instanceId",
                        "status"
                      ],
                      "title": "Provisioning started"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Unauthorized",
                            "Invalid callbackUrl: must be HTTPS and not target internal networks"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "The worker's refusal, passed on with a 202.",
                      "title": "Refused by the background worker",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "provisioning_unavailable",
                        "invalid_url"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and the provisioning worker: the run was queued.",
                    "value": {
                      "instanceId": "00000000-0000-4000-8000-000000000104",
                      "status": {
                        "status": "queued"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- workspace.name is required: `workspace.name` is missing.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace.name is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "workspace.name is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `provision_rate_limit`: The account has already made 120 provisioning requests this minute, or 1,000 this hour.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "$ref": "#/components/schemas/ProvisionRateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to trigger async provisioning: The worker could not be reached, or did not answer with JSON.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to trigger async provisioning"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to trigger async provisioning",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- Async provisioning is not configured: No background worker is configured.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Async provisioning is not configured"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "provisioning_unavailable"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "Async provisioning is not configured",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "provisioning_unavailable"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/provision/bulk": {
      "post": {
        "operationId": "provisionEnterpriseWorkspacesBulk",
        "summary": "Provision workspaces in bulk",
        "description": "Creates up to 100 workspaces, each optionally sharing a verification and taking credits, and reports each one. A request with `callbackUrl` or a field only the background worker applies goes to the worker instead, which answers 202.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "provisionBulk"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The workspaces to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "workspaces": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "sourceWorkspaceId": {
                          "type": "string",
                          "description": "Share this workspace's verification. Also read as `source_workspace_id` and `inheritVerificationFrom`. A workspace the key's owner does not own is skipped silently."
                        },
                        "creditAmount": {
                          "type": "integer",
                          "minimum": 1,
                          "description": "Also read as `credit_amount`."
                        },
                        "creditSourceWorkspaceId": {
                          "type": "string",
                          "description": "A workspace id (a UUID). Also read as `credit_source_workspace_id`."
                        }
                      },
                      "required": [
                        "name"
                      ],
                      "description": "Any of `verification`, `verificationOverrides`, `inheritWithNewNumber`, `keyName`, `generateOptInPage` or `webhookUrl` (in either spelling) sends the whole request to the background worker; without a worker it is refused."
                    },
                    "minItems": 1,
                    "maxItems": 100
                  },
                  "callbackUrl": {
                    "type": "string",
                    "description": "Sends the request to the background worker, which posts each result here."
                  }
                },
                "required": [
                  "workspaces"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- EnterpriseBulkProvisionResult: Every workspace was attempted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseBulkProvisionResult"
                },
                "examples": {
                  "default": {
                    "summary": "Built from executeBulkProvision: one created, one created without its credits, one refused.",
                    "value": {
                      "results": [
                        {
                          "name": "Acme North",
                          "status": "success",
                          "success": true,
                          "workspaceId": "00000000-0000-4000-8000-000000000101",
                          "slug": "acme-north"
                        },
                        {
                          "name": "Acme South",
                          "status": "partial",
                          "success": true,
                          "workspaceId": "00000000-0000-4000-8000-000000000105",
                          "slug": "acme-south",
                          "warning": "Credit transfer failed: Insufficient credits"
                        },
                        {
                          "name": "Acme  North",
                          "status": "failed",
                          "success": false,
                          "error": "Workspace with similar name exists"
                        }
                      ],
                      "summary": {
                        "total": 3,
                        "succeeded": 2,
                        "failed": 1
                      },
                      "totalRequested": 3,
                      "totalCreated": 2,
                      "totalFailed": 1
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted.\n\n- Handed to the background worker: The background worker started a run for each workspace.\n- Refused by the background worker: The background worker refused the request.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "instances": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "workspaceName": {
                                "type": "string"
                              },
                              "instanceId": {
                                "type": "string",
                                "description": "The run's id."
                              }
                            },
                            "required": [
                              "instanceId"
                            ]
                          }
                        },
                        "total": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "instances",
                        "total"
                      ],
                      "title": "Handed to the background worker"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Unauthorized",
                            "Invalid callbackUrl: must be HTTPS and not target internal networks"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "The worker's refusal, passed on with a 202.",
                      "title": "Refused by the background worker",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "provisioning_unavailable",
                        "invalid_url"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- Invalid bulk request: The request is malformed, or needs the background worker and none is configured.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` says what is wrong: `workspaces array is required`, `Maximum 100 workspaces per bulk provision`, `Duplicate workspace names in request`, `Each workspace must be an object`, `Each workspace name must be a string`, an invalid `sourceWorkspaceId`, `creditAmount` or `creditSourceWorkspaceId` for a named workspace, `workspaces[] array is required` or `Maximum 100 workspaces per bulk request` on the worker path, or that fields only the worker applies cannot be applied right now.",
                      "title": "Invalid bulk request",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- Would exceed workspace limit: The workspaces would take the enterprise account past its most workspaces. None is created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Would exceed workspace limit"
                          ]
                        },
                        "currentCount": {
                          "type": "integer"
                        },
                        "maxWorkspaces": {
                          "type": "integer"
                        },
                        "requested": {
                          "type": "integer"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "workspace_limit_reached"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error",
                        "currentCount",
                        "maxWorkspaces",
                        "requested"
                      ],
                      "title": "Would exceed workspace limit",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "workspace_limit_reached"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `provision_rate_limit`: The account has already made 120 provisioning requests this minute, or 1,000 this hour.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "$ref": "#/components/schemas/ProvisionRateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to bulk provision workspaces: Provisioning failed unexpectedly.\n- Failed to trigger bulk provisioning: The background worker could not be reached, or did not answer with JSON.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to bulk provision workspaces"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to bulk provision workspaces",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to trigger bulk provisioning"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to trigger bulk provisioning",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/provision/status/{instanceId}": {
      "get": {
        "operationId": "getEnterpriseProvisionStatus",
        "summary": "Get a background provisioning run",
        "description": "Returns the state of a run started by `POST /provision/async` or a bulk provision handed to the worker. The worker's own error statuses are passed on.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The run's id, a UUID."
            },
            "required": true,
            "name": "instanceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Provisioning run: The run's state.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "instanceId": {
                      "type": "string",
                      "description": "The provisioning run's id. Poll `GET /provision/status/{instanceId}` with it."
                    },
                    "status": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "description": "Where the provisioning run is. Known values: `queued`, `running`, `paused`, `errored`, `terminated`, `complete`, `waiting`, `waitingForPause`, `unknown`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "queued",
                            "running",
                            "paused",
                            "errored",
                            "terminated",
                            "complete",
                            "waiting",
                            "waitingForPause",
                            "unknown"
                          ]
                        },
                        "error": {
                          "description": "Why the run failed."
                        },
                        "output": {
                          "description": "When the run is complete, what `POST /api/v1/enterprise/workspaces/provision` answered, including any new API key in full."
                        }
                      },
                      "required": [
                        "status"
                      ],
                      "description": "The provisioning run's state, as the background worker reports it."
                    }
                  },
                  "required": [
                    "instanceId",
                    "status"
                  ],
                  "title": "Provisioning run"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and the provisioning worker: the run is in progress.",
                    "value": {
                      "instanceId": "00000000-0000-4000-8000-000000000104",
                      "status": {
                        "status": "running"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- Invalid instance ID: `instanceId` is not a UUID.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Invalid instance ID"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Invalid instance ID",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- Unauthorized: The worker refused the server's own credentials.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Unauthorized"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "provisioning_unavailable"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Unauthorized",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "provisioning_unavailable"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- Instance not found: The worker has no run with this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Instance not found"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "not_found"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "Instance not found",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "not_found"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch provisioning status: The worker could not be reached, or did not answer with JSON.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch provisioning status"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to fetch provisioning status",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- Async provisioning is not configured: No background worker is configured.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Async provisioning is not configured"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "provisioning_unavailable"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "Async provisioning is not configured",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "provisioning_unavailable"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}": {
      "get": {
        "operationId": "getEnterpriseWorkspace",
        "summary": "Get a workspace",
        "description": "Returns one workspace with its verification, credit balance and key count.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseWorkspaceDetail: The workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceDetail"
                },
                "examples": {
                  "default": {
                    "summary": "A verified workspace: built from the handler.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000010",
                      "name": "Acme Clinics",
                      "slug": "acme-clinics",
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "verification": {
                        "status": "verified",
                        "type": "toll_free",
                        "tollFreeNumber": "+15555550100",
                        "businessName": "Acme Clinics LLC"
                      },
                      "credits": 1500,
                      "keyCount": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "unknown-key": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch workspace: The workspace could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteEnterpriseWorkspace",
        "summary": "Delete a workspace",
        "description": "Deletes the workspace and everything stored in it, including its keys and phone number records, removes its messaging profile unless another workspace uses it, and updates the account's per-workspace billing. It refuses with 409 while the workspace holds or owes credits, while it has a number that is never released with a workspace (a ported number, one marked as needing support, or one in a port still in progress), and while it has any other phone number, unless `release_numbers=true` is sent: each number is then released at the carrier first, and the workspace is kept when any release fails. A number another workspace still uses is left alone.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "delete"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "1"
              ],
              "description": "`true` or `1` releases the workspace's numbers at the carrier before deleting it. `releaseNumbers` is read too, and so is `release_numbers: true` in a JSON body."
            },
            "required": false,
            "name": "release_numbers",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseWorkspaceDeleted: The workspace was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceDeleted"
                },
                "examples": {
                  "default": {
                    "summary": "A workspace was deleted: built from the handler, since deleting one changes billing.",
                    "value": {
                      "success": true,
                      "deletedId": "00000000-0000-4000-8000-000000000010"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to delete a workspace that does not exist.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `workspace_has_credits`, `workspace_balance_negative`: The workspace holds credits or has credits reserved (`workspace_has_credits`), or owes credits (`workspace_balance_negative`).\n- `workspace_has_unreleasable_numbers`: The workspace has a number that is never released with a workspace.\n- `workspace_has_numbers`: The workspace has phone numbers and `release_numbers=true` was not sent.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_has_credits",
                            "workspace_balance_negative"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "balance": {
                          "type": "number",
                          "description": "The workspace's credit balance."
                        },
                        "reservedBalance": {
                          "type": "number",
                          "description": "Credits held for messages still being sent."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "balance",
                        "reservedBalance"
                      ],
                      "title": "workspace_has_credits, workspace_balance_negative",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_has_credits",
                        "workspace_balance_negative"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_has_unreleasable_numbers"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "numbers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "The number's id."
                              },
                              "phoneNumber": {
                                "type": "string",
                                "description": "The number, in E.164 format."
                              },
                              "source": {
                                "type": "string",
                                "description": "How the workspace got the number, such as `purchased`, `ported` or `hosted`."
                              },
                              "portRequestId": {
                                "type": "string",
                                "description": "The port in progress, for a number it is bringing in."
                              },
                              "reason": {
                                "type": "string",
                                "enum": [
                                  "ported_number",
                                  "needs_support",
                                  "port_in_progress"
                                ]
                              }
                            },
                            "required": [
                              "id",
                              "phoneNumber",
                              "source",
                              "reason"
                            ]
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "numbers"
                      ],
                      "title": "workspace_has_unreleasable_numbers",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_has_unreleasable_numbers"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_has_numbers"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "numbers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "The number's id."
                              },
                              "phoneNumber": {
                                "type": "string",
                                "description": "The number, in E.164 format."
                              },
                              "source": {
                                "type": "string",
                                "description": "How the workspace got the number, such as `purchased`, `ported` or `hosted`."
                              }
                            },
                            "required": [
                              "id",
                              "phoneNumber",
                              "source"
                            ]
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "numbers"
                      ],
                      "title": "workspace_has_numbers",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_has_numbers"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to delete workspace: The workspace could not be deleted, or the workspaces left could not be counted after it was. A failure to update billing does not answer this.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to delete workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to delete workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `number_release_failed`: `release_numbers=true` was sent and the carrier did not release every number, so the workspace was kept.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "number_release_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "failed": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The numbers the carrier did not release."
                    },
                    "released": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The numbers released before the failure."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "failed",
                    "released"
                  ],
                  "title": "number_release_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "number_release_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/credits": {
      "get": {
        "operationId": "getEnterpriseWorkspaceCredits",
        "summary": "Get a workspace's credits",
        "description": "Returns the workspace's own credit balance. In pooled credit mode the workspace spends from the account's pool, which this does not include.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "getCredits"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseWorkspaceCredits: The workspace's balance.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceCredits"
                },
                "examples": {
                  "default": {
                    "summary": "A workspace's balance: built from the handler.",
                    "value": {
                      "balance": 1500,
                      "lifetimeCredits": 5000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch credits: The balance could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch credits"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch credits",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/invitations": {
      "get": {
        "operationId": "listEnterpriseWorkspaceInvitations",
        "summary": "List a workspace's invitations",
        "description": "Lists every invitation to the workspace, in any status, newest first.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "listInvitations"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The invitations, as a bare array.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnterpriseWorkspaceInvitation"
                  }
                },
                "examples": {
                  "default": {
                    "summary": "A workspace's invitations: built from the handler, which drops each row's token.",
                    "value": [
                      {
                        "id": "00000000-0000-4000-8000-000000000040",
                        "organizationId": "00000000-0000-4000-8000-000000000010",
                        "email": "user@example.com",
                        "role": "member",
                        "invitedBy": "00000000-0000-4000-8000-000000000020",
                        "status": "pending",
                        "expiresAt": "2026-01-08T00:00:00.000Z",
                        "acceptedAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch invitations: The invitations could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch invitations"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to fetch invitations",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createEnterpriseWorkspaceInvitation",
        "summary": "Invite someone to a workspace",
        "description": "Invites an email address to join the workspace with a role, for 7 days. No invitation email is sent: the route emails only for a workspace outside any enterprise account, and every workspace this route reaches is in one.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "sendInvitation"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "Who to invite, and as what.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "The invitee's email address."
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "member",
                      "viewer"
                    ],
                    "description": "Required."
                  }
                },
                "required": [
                  "email",
                  "role"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- EnterpriseWorkspaceInvitationCreated: The invitation was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceInvitationCreated"
                },
                "examples": {
                  "default": {
                    "summary": "An invitation was created: built from the handler, since an invitation can email a real person.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000040",
                      "email": "user@example.com",
                      "role": "member",
                      "status": "pending",
                      "expiresAt": "2026-01-08T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- email is required: `email` is missing or not a string.\n- Invalid email format: `email` is not an email address.\n- Invalid role. Must be admin, member, or viewer: `role` is missing or not one of the three.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "email is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "email is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Invalid email format"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Invalid email format",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Invalid role. Must be admin, member, or viewer"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Invalid role. Must be admin, member, or viewer",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A body that is not valid JSON, answered by the body parser.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to invite someone.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- User is already a member: Someone with that email is already a member.\n- Invitation already sent to this email: A pending invitation to that email exists.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "User is already a member"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "already_member"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "User is already a member",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "already_member"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Invitation already sent to this email"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invitation_exists"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Invitation already sent to this email",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invitation_exists"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to create invitation: The invitation could not be created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to create invitation"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to create invitation",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/invitations/{inviteId}": {
      "delete": {
        "operationId": "cancelEnterpriseWorkspaceInvitation",
        "summary": "Cancel an invitation",
        "description": "Marks the invitation cancelled. It answers success for any `inviteId`, one that matches nothing included, and does not check that the invitation is the workspace's.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "cancelInvitation"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The invitation's id."
            },
            "required": true,
            "name": "inviteId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The invitation is cancelled, or no invitation has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An invitation was cancelled: built from the handler.",
                    "value": {
                      "success": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to cancel an invitation.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to cancel invitation: The invitation could not be updated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to cancel invitation"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to cancel invitation",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/keys": {
      "get": {
        "operationId": "listEnterpriseWorkspaceKeys",
        "summary": "List a workspace's API keys",
        "description": "Lists the workspace's active API keys, newest first, without their secrets.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "listKeys"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The keys, as a bare array.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnterpriseWorkspaceKey"
                  }
                },
                "examples": {
                  "default": {
                    "summary": "A workspace's active keys: built from the handler.",
                    "value": [
                      {
                        "id": "00000000-0000-4000-8000-000000000050",
                        "name": "API key",
                        "keyPrefix": "sk_test_v1_a",
                        "type": "test",
                        "scopes": [
                          "sms:send",
                          "sms:read"
                        ],
                        "lastUsedAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to list API keys: The keys could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to list API keys"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to list API keys",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createEnterpriseWorkspaceKey",
        "summary": "Create an API key for a workspace",
        "description": "Creates an API key in the workspace. The secret is in `key`, and only in this answer. A live key needs the workspace to be verified and to have credits: its own, or in pooled mode the pool and overage allowance.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "createKey"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The key to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Defaults to `API key`, which a blank name gives too."
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "test",
                      "live"
                    ],
                    "description": "Defaults to `test`."
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "The key's scopes, stored as sent. Defaults to `sms:send`, `sms:read`, `verify:send`, `verify:read`, `webhooks:read`, `webhooks:write`, `templates:read`, `templates:write`, `campaigns:read`, `campaigns:write`, `campaigns:send`, `contacts:read`, `contacts:write`, `numbers:read`, `numbers:write`, `tendlc:read`, `tendlc:write`, `rcs:read`, `rcs:write`, `whatsapp:read`, `whatsapp:write`, `short_codes:read`, `short_codes:write`, `links:read`, `links:write`, `calls:read` and `calls:write`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- EnterpriseWorkspaceKeyCreated: The key was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceKeyCreated"
                },
                "examples": {
                  "default": {
                    "summary": "A test key was created: built from the handler, since creating one through an enterprise master key is not safe to run.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000050",
                      "name": "Front desk",
                      "key": "sk_test_v1_placeholder",
                      "keyPrefix": "sk_test_v1_a",
                      "type": "test",
                      "scopes": [
                        "sms:send",
                        "sms:read"
                      ],
                      "createdAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- name must be a string: `name` is neither a string nor `null`.\n- type must be 'test' or 'live': `type` is not `test` or `live`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "name must be a string"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "name must be a string",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "type must be 'test' or 'live'"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "type must be 'test' or 'live'",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "unknown-key": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- Workspace must have credits before creating live keys: A live key for a workspace with no credits to spend.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Workspace must have credits before creating live keys"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "credits_required"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "`error` holds a sentence, and there is no `message`.",
                  "title": "Workspace must have credits before creating live keys",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "credits_required"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).\n- Workspace must be verified before creating live keys: A live key for a workspace whose verification is not approved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Workspace must be verified before creating live keys"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "verification_required"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Workspace must be verified before creating live keys",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "verification_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to create a key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to create API key: The key could not be created, as when `scopes` is not an array of strings.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to create API key"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to create API key",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/keys/{keyId}": {
      "delete": {
        "operationId": "revokeEnterpriseWorkspaceKey",
        "summary": "Revoke a workspace's API key",
        "description": "Revokes one of the workspace's API keys at once.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "revokeKey"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The key's id."
            },
            "required": true,
            "name": "keyId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseWorkspaceKeyRevoked: The key was revoked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceKeyRevoked"
                },
                "examples": {
                  "default": {
                    "summary": "A key was revoked: built from the handler. Since main's #204 (31e3c657) the revoke passes the workspace, so production sends this for an active key of the workspace.",
                    "value": {
                      "success": true,
                      "revokedId": "00000000-0000-4000-8000-000000000050"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).\n- Key does not belong to this workspace: The key exists, in another workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Key does not belong to this workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "access_denied"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Key does not belong to this workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "access_denied"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to revoke a key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.\n- API key not found: No key has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "API key not found"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "not_found"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "API key not found",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "not_found"
                      ]
                    }
                  ]
                },
                "examples": {
                  "missing-key": {
                    "summary": "No key has this id: built from the handler.",
                    "value": {
                      "error": "API key not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- API key is already revoked: The key was revoked before.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "API key is already revoked"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "already_revoked"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "`error` holds a sentence, and there is no `message`.",
                  "title": "API key is already revoked",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "already_revoked"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to revoke API key: The key could not be read or revoked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to revoke API key"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to revoke API key",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the key could not be read or revoked, as when the database fails. Since main's #204 (31e3c657) a revoke of an active key in the workspace succeeds, so this is no longer what every revoke answers.",
                    "value": {
                      "error": "Failed to revoke API key"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/opt-in-pages": {
      "get": {
        "operationId": "listEnterpriseWorkspaceOptInPages",
        "summary": "List a workspace's opt-in pages",
        "description": "Lists the workspace's hosted pages, newest first: its opt-in pages, and its privacy and terms pages too.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "listOptInPages"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The pages, as a bare array.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnterpriseOptInPageListItem"
                  }
                },
                "examples": {
                  "default": {
                    "summary": "A workspace's opt-in pages: built from the handler.",
                    "value": [
                      {
                        "id": "00000000-0000-4000-8000-000000000060",
                        "slug": "acme-clinics-x7k2",
                        "url": "https://sendly.live/opt-in/acme-clinics-x7k2",
                        "businessName": "Acme Clinics",
                        "useCase": "appointment_reminders",
                        "isActive": true,
                        "viewCount": 12,
                        "logoUrl": null,
                        "headerColor": "#334155",
                        "buttonColor": "#667eea",
                        "customHeadline": null,
                        "createdAt": "2026-01-01T00:00:00.000Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to list opt-in pages: The pages could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to list opt-in pages"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to list opt-in pages",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createEnterpriseWorkspaceOptInPage",
        "summary": "Create an opt-in page",
        "description": "Creates a hosted opt-in page for the workspace, at a slug made from the business name, a hyphen and up to four random characters.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "createOptInPage"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The page to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "businessName": {
                    "type": "string",
                    "minLength": 1
                  },
                  "useCase": {
                    "type": "string"
                  },
                  "useCaseSummary": {
                    "type": "string"
                  },
                  "sampleMessages": {
                    "type": "string"
                  }
                },
                "required": [
                  "businessName"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- EnterpriseOptInPageCreated: The page was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseOptInPageCreated"
                },
                "examples": {
                  "default": {
                    "summary": "An opt-in page was created: built from the handler.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000060",
                      "slug": "acme-clinics-x7k2",
                      "url": "https://sendly.live/opt-in/acme-clinics-x7k2",
                      "businessName": "Acme Clinics"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- businessName is required: `businessName` is missing or empty.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "businessName is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "businessName is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    }
                  ]
                },
                "examples": {
                  "missing-name": {
                    "summary": "The business name is missing: built from the handler.",
                    "value": {
                      "error": "businessName is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to create an opt-in page.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to create opt-in page: The page could not be created, as when `businessName` is not a string.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to create opt-in page"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to create opt-in page",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/opt-in-pages/{pageId}": {
      "patch": {
        "operationId": "updateEnterpriseWorkspaceOptInPage",
        "summary": "Customize an opt-in page",
        "description": "Changes the page's logo, colors, headline or benefits. Send at least one of them: a body with none answers 500.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "updateOptInPage"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The page's slug, or its id."
            },
            "required": true,
            "name": "pageId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change. Each is stored as sent, unchecked.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "logoUrl": {
                    "type": "string"
                  },
                  "headerColor": {
                    "type": "string",
                    "description": "A hex color, such as `#334155`."
                  },
                  "buttonColor": {
                    "type": "string",
                    "description": "A hex color, such as `#667eea`."
                  },
                  "customHeadline": {
                    "type": "string"
                  },
                  "customBenefits": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseOptInPage: The page, as changed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseOptInPage"
                },
                "examples": {
                  "default": {
                    "summary": "An opt-in page was customized: built from the handler and withOptInPageUrl, which return every stored field.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000060",
                      "userId": "00000000-0000-4000-8000-000000000020",
                      "organizationId": "00000000-0000-4000-8000-000000000010",
                      "verificationId": null,
                      "slug": "acme-clinics-x7k2",
                      "pageType": "opt_in",
                      "businessName": "Acme Clinics",
                      "useCase": "appointment_reminders",
                      "useCaseSummary": null,
                      "sampleMessages": null,
                      "effectiveDate": "2026-01-01T00:00:00.000Z",
                      "businessAddress": null,
                      "contactEmail": null,
                      "contactPhone": null,
                      "socialUrl": null,
                      "logoUrl": null,
                      "headerColor": "#0f172a",
                      "buttonColor": "#667eea",
                      "customHeadline": "Get reminders by text",
                      "customBenefits": null,
                      "customConsentText": null,
                      "screenshotUrl": null,
                      "screenshotCapturedAt": null,
                      "isActive": true,
                      "viewCount": 12,
                      "customDomain": null,
                      "domainVerified": false,
                      "domainVerificationToken": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "url": "https://sendly.live/opt-in/acme-clinics-x7k2"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).\n- Page does not belong to this workspace: `pageId` is the slug of a page in another workspace, or in none.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Page does not belong to this workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "access_denied"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Page does not belong to this workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "access_denied"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to customize an opt-in page.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.\n- Opt-in page not found: No page has this slug or id in the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Opt-in page not found"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "not_found"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Opt-in page not found",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to update opt-in page: The body has none of the five fields, or the page could not be updated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to update opt-in page"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to update opt-in page",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteEnterpriseWorkspaceOptInPage",
        "summary": "Delete an opt-in page",
        "description": "Deletes one of the workspace's hosted pages, which stops answering at once.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "deleteOptInPage"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The page's id. A slug is not accepted here."
            },
            "required": true,
            "name": "pageId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The page was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An opt-in page was deleted: built from the handler.",
                    "value": {
                      "success": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to delete an opt-in page.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.\n- Opt-in page not found: No page with this id is in the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Opt-in page not found"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "not_found"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Opt-in page not found",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "not_found"
                      ]
                    }
                  ]
                },
                "examples": {
                  "missing-page": {
                    "summary": "No page with this id is in the workspace: built from the handler.",
                    "value": {
                      "error": "Opt-in page not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to delete opt-in page: The page could not be deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to delete opt-in page"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to delete opt-in page",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/pages/{pageId}/domain": {
      "put": {
        "operationId": "setEnterpriseWorkspacePageDomain",
        "summary": "Set a page's custom domain",
        "description": "Points a custom domain at one of the workspace's hosted pages, unverified, and returns the DNS records that verify it. Each call makes a new TXT token. It answers the same when no page with `pageId` is in the workspace, though nothing is stored then.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "setCustomDomain"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The page's id."
            },
            "required": true,
            "name": "pageId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The domain to use.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain": {
                    "type": "string",
                    "maxLength": 253,
                    "description": "A host name, such as `optin.example.com`. Stored in lower case."
                  }
                },
                "required": [
                  "domain"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseCustomDomainSetup: The domain was set, or nothing matched `pageId`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseCustomDomainSetup"
                },
                "examples": {
                  "default": {
                    "summary": "A custom domain was set: built from the handler.",
                    "value": {
                      "domain": "optin.example.com",
                      "verified": false,
                      "dnsInstructions": {
                        "cname": {
                          "type": "CNAME",
                          "name": "optin.example.com",
                          "value": "sendly.live"
                        },
                        "txt": {
                          "type": "TXT",
                          "name": "_sendly-verify.optin.example.com",
                          "value": "0123456789abcdef0123456789abcdef"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- domain is required: `domain` is missing, empty or not a string.\n- Domain name too long: `domain` is longer than 253 characters.\n- Invalid domain format: `domain` is not a host name.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "domain is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "domain is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Domain name too long"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Domain name too long",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Invalid domain format"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Invalid domain format",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-domain": {
                    "summary": "A domain that is not a host name: built from the handler.",
                    "value": {
                      "error": "Invalid domain format"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "unknown-key": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key, which is not an enterprise master key, asked to set a custom domain.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to set custom domain: The domain could not be stored.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to set custom domain"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Failed to set custom domain",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/quota": {
      "get": {
        "operationId": "getEnterpriseWorkspaceQuota",
        "summary": "Get a workspace's message quota",
        "description": "Returns the workspace's monthly message quota and how much of it is used.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "getQuota"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseWorkspaceQuota: The quota.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceQuota"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the workspace's quota fields as stored.",
                    "value": {
                      "monthlyMessageQuota": 5000,
                      "messagesThisMonth": 1240,
                      "quotaResetAt": "2026-10-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch quota: The quota could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch quota"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to fetch quota",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "setEnterpriseWorkspaceQuota",
        "summary": "Set a workspace's message quota",
        "description": "Sets the most messages the workspace may send a month, or removes the limit with `null`.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "setQuota"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The new quota.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "monthlyMessageQuota": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "description": "A whole number of 1 or more, or `null` for no limit. A numeric string such as `\"500\"` is read as a number. Leaving it out is not the same as `null`: the save fails with a 500."
                  }
                },
                "required": [
                  "monthlyMessageQuota"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseWorkspaceQuota: The quota was saved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceQuota"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the saved quota.",
                    "value": {
                      "monthlyMessageQuota": 5000,
                      "messagesThisMonth": 1240,
                      "quotaResetAt": "2026-10-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- monthlyMessageQuota must be a positive integer or null: `monthlyMessageQuota` is not a whole number of 1 or more, nor `null`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "monthlyMessageQuota must be a positive integer or null"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "monthlyMessageQuota must be a positive integer or null",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to update quota: The quota could not be saved, as when `monthlyMessageQuota` is left out of the body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to update quota"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to update quota",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/resume": {
      "post": {
        "operationId": "resumeEnterpriseWorkspace",
        "summary": "Resume a workspace",
        "description": "Turns the sending profile of a suspended workspace back on and makes the workspace active. Sends a `workspace.resumed` enterprise webhook.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "resume"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The workspace is active again.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The workspace's id."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active"
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "status"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the workspace as resumeOrganization returns it.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "status": "active"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- Workspace is not suspended: The workspace is not suspended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Workspace is not suspended"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "invalid_state"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "Workspace is not suspended",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "invalid_state"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to resume workspace: The workspace could not be resumed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to resume workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to resume workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- Failed to enable messaging profile. Workspace remains suspended.: The sending profile could not be turned back on, so the workspace stays suspended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Failed to enable messaging profile. Workspace remains suspended."
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "messaging_profile_update_failed"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "Failed to enable messaging profile. Workspace remains suspended.",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "messaging_profile_update_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/suspend": {
      "post": {
        "operationId": "suspendEnterpriseWorkspace",
        "summary": "Suspend a workspace",
        "description": "Suspends the workspace and turns off its sending profile, so it can no longer send. Sends a `workspace.suspended` enterprise webhook.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "suspend"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "An optional reason.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "Why the workspace is suspended, kept with it."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- The workspace is suspended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The workspace's id."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "suspended"
                      ]
                    },
                    "suspendedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "When the workspace was suspended. ISO 8601, in UTC."
                    }
                  },
                  "required": [
                    "id",
                    "status",
                    "suspendedAt"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the workspace as suspendOrganization returns it.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "status": "suspended",
                      "suspendedAt": "2026-10-03T12:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- Workspace is already suspended: The workspace is already suspended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Workspace is already suspended"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "invalid_state"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "Workspace is already suspended",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "invalid_state"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to suspend workspace: The workspace could not be suspended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to suspend workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to suspend workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- Failed to disable messaging profile. Suspension rolled back.: The sending profile could not be turned off, so the suspension was undone and the workspace is active again.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Failed to disable messaging profile. Suspension rolled back."
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "messaging_profile_update_failed"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "Failed to disable messaging profile. Suspension rolled back.",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "messaging_profile_update_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/transfer-credits": {
      "post": {
        "operationId": "transferEnterpriseWorkspaceCredits",
        "summary": "Move credits into a workspace",
        "description": "Moves credits from another workspace the key's owner owns, which may be the personal one, into this workspace. Sends a `credits.transferred` enterprise webhook.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "transferCredits"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "Where the credits come from, and how many.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "sourceWorkspaceId": {
                        "type": "string",
                        "description": "The workspace to take from."
                      },
                      "amount": {
                        "type": "integer",
                        "minimum": 1,
                        "description": "Credits to move: a whole number of 1 or more, not a string."
                      }
                    },
                    "required": [
                      "sourceWorkspaceId",
                      "amount"
                    ],
                    "title": "sourceWorkspaceId"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "source_workspace_id": {
                        "type": "string",
                        "description": "The workspace to take from. Read when `sourceWorkspaceId` is absent."
                      },
                      "amount": {
                        "type": "integer",
                        "minimum": 1,
                        "description": "Credits to move: a whole number of 1 or more, not a string."
                      }
                    },
                    "required": [
                      "source_workspace_id",
                      "amount"
                    ],
                    "title": "source_workspace_id"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- The credits were moved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "amount": {
                      "type": "integer",
                      "description": "Credits moved."
                    },
                    "sourceBalance": {
                      "type": "integer",
                      "description": "The source workspace's balance after the move."
                    },
                    "targetBalance": {
                      "type": "integer",
                      "description": "This workspace's balance after the move."
                    }
                  },
                  "required": [
                    "success",
                    "amount",
                    "sourceBalance",
                    "targetBalance"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from transferCreditsV1: both balances after the move.",
                    "value": {
                      "success": true,
                      "amount": 500,
                      "sourceBalance": 1500,
                      "targetBalance": 700
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- sourceWorkspaceId is required: No source workspace, or one that is not a string.\n- amount must be a positive integer: `amount` is not a whole number of 1 or more.\n- Cannot transfer to the same workspace: The source workspace is this workspace.\n- Insufficient credits: The source workspace has fewer credits than `amount`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "sourceWorkspaceId is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "sourceWorkspaceId is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "amount must be a positive integer"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "amount must be a positive integer",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Cannot transfer to the same workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Cannot transfer to the same workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Insufficient credits"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "insufficient_credits"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Insufficient credits",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "insufficient_credits"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).\n- You must own the source workspace: No workspace has the source id, or the key's owner does not own it.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "You must own the source workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "not_workspace_owner"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "You must own the source workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "not_workspace_owner"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to transfer credits: The credits could not be moved, as when either workspace has no credit balance row.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to transfer credits"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to transfer credits",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/verification": {
      "get": {
        "operationId": "getEnterpriseWorkspaceVerification",
        "summary": "Get a workspace's verification",
        "description": "Returns the workspace's business verification, or `status: none` when it has none.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "getVerification"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Verification: The workspace has a verification.\n- No verification: The workspace has no verification yet.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "verificationId": {
                          "type": "string",
                          "description": "The verification's id."
                        },
                        "status": {
                          "type": "string",
                          "description": "The verification's status. `processing` means the carrier is reviewing it, `action_required` that it needs changes from you. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `processing`, `action_required`, `verified`, `rejected`, `archived`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "pending",
                            "pending_review",
                            "submitted",
                            "in_progress",
                            "processing",
                            "action_required",
                            "verified",
                            "rejected",
                            "archived"
                          ]
                        },
                        "type": {
                          "type": "string",
                          "description": "What the verification covers. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "toll_free",
                            "international",
                            "both"
                          ]
                        },
                        "tollFreeNumber": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The workspace's toll-free number in E.164 format, or `null` before one is set."
                        },
                        "businessName": {
                          "type": "string"
                        },
                        "submittedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the verification was created. ISO 8601, in UTC."
                        }
                      },
                      "required": [
                        "verificationId",
                        "status",
                        "type",
                        "tollFreeNumber",
                        "businessName",
                        "submittedAt"
                      ],
                      "title": "Verification"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "none"
                          ]
                        }
                      },
                      "required": [
                        "status"
                      ],
                      "title": "No verification"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: a verification the carrier is reviewing.",
                    "value": {
                      "verificationId": "00000000-0000-4000-8000-000000000103",
                      "status": "processing",
                      "type": "toll_free",
                      "tollFreeNumber": "+15555550142",
                      "businessName": "Acme Dental",
                      "submittedAt": "2026-10-01T09:30:00.000Z"
                    }
                  },
                  "none": {
                    "summary": "Built from the handler: a workspace with no verification.",
                    "value": {
                      "status": "none"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to fetch verification status: The verification could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to fetch verification status"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to fetch verification status",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/verification/inherit": {
      "post": {
        "operationId": "inheritEnterpriseWorkspaceVerification",
        "summary": "Inherit a workspace's verification",
        "description": "Gives this workspace the verification of another workspace the key's owner owns. By default it shares the source's number and status. With `purchaseNewNumber`, it copies the business details, creates a sending profile, buys a toll-free number and submits the verification for it; that costs money.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "inheritVerification"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The workspace to inherit from.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "sourceWorkspaceId": {
                        "type": "string",
                        "description": "The workspace to take from."
                      },
                      "purchaseNewNumber": {
                        "type": "boolean",
                        "description": "Buy a new toll-free number for this workspace instead of sharing the source's."
                      }
                    },
                    "required": [
                      "sourceWorkspaceId"
                    ],
                    "title": "sourceWorkspaceId"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "source_workspace_id": {
                        "type": "string",
                        "description": "The workspace to take from. Read when `sourceWorkspaceId` is absent."
                      },
                      "purchaseNewNumber": {
                        "type": "boolean",
                        "description": "Buy a new toll-free number for this workspace instead of sharing the source's."
                      }
                    },
                    "required": [
                      "source_workspace_id"
                    ],
                    "title": "source_workspace_id"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- Verification shared: The workspace shares the source's verification and number.\n- Verification copied, with a new number: The business details were copied, and a number bought and submitted where that worked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "verificationId": {
                          "type": "string",
                          "description": "The new verification's id."
                        },
                        "status": {
                          "type": "string",
                          "description": "The verification's status as stored, not the public form `GET /verification` gives: `waiting_for_customer` here is `action_required` there, and `waiting_for_vendor` (and one more internal waiting status) is `processing` there. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `waiting_for_vendor`, `waiting_for_customer`, `verified`, `rejected`, `archived`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "pending",
                            "pending_review",
                            "submitted",
                            "in_progress",
                            "waiting_for_vendor",
                            "waiting_for_customer",
                            "verified",
                            "rejected",
                            "archived"
                          ]
                        },
                        "type": {
                          "type": "string",
                          "description": "What the verification covers. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "toll_free",
                            "international",
                            "both"
                          ]
                        },
                        "tollFreeNumber": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The source workspace's toll-free number, which this workspace now shares."
                        },
                        "inheritedFrom": {
                          "type": "string",
                          "description": "The source workspace's id."
                        }
                      },
                      "required": [
                        "verificationId",
                        "status",
                        "type",
                        "tollFreeNumber",
                        "inheritedFrom"
                      ],
                      "title": "Verification shared"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "verificationId": {
                          "type": "string",
                          "description": "The new verification's id."
                        },
                        "status": {
                          "type": "string",
                          "description": "`submitted` when a new number was bought and the verification was sent for review; `pending` otherwise. Known values: `pending`, `submitted`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "pending",
                            "submitted"
                          ]
                        },
                        "type": {
                          "type": "string",
                          "description": "What the verification covers. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "toll_free",
                            "international",
                            "both"
                          ]
                        },
                        "tollFreeNumber": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The new toll-free number, or `null` when none could be bought."
                        },
                        "inheritedFrom": {
                          "type": "string",
                          "description": "The source workspace's id."
                        },
                        "newNumber": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "verificationId",
                        "status",
                        "type",
                        "tollFreeNumber",
                        "inheritedFrom",
                        "newNumber"
                      ],
                      "title": "Verification copied, with a new number"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the shared verification, with the source's stored status.",
                    "value": {
                      "verificationId": "00000000-0000-4000-8000-000000000103",
                      "status": "verified",
                      "type": "toll_free",
                      "tollFreeNumber": "+15555550142",
                      "inheritedFrom": "00000000-0000-4000-8000-000000000102"
                    }
                  },
                  "new-number": {
                    "summary": "Built from the handler: copied details, a new number bought and submitted.",
                    "value": {
                      "verificationId": "00000000-0000-4000-8000-000000000103",
                      "status": "submitted",
                      "type": "toll_free",
                      "tollFreeNumber": "+15555550144",
                      "inheritedFrom": "00000000-0000-4000-8000-000000000102",
                      "newNumber": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- sourceWorkspaceId is required: No source workspace, or one that is not a string.\n- Source workspace has no active verification: The source workspace has no verification, or one without a sending profile.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "sourceWorkspaceId is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "sourceWorkspaceId is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Source workspace has no active verification"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "not_verified"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Source workspace has no active verification",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "not_verified"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).\n- You must own the source workspace: No workspace has the source id, or the key's owner does not own it.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "You must own the source workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "not_workspace_owner"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "You must own the source workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "not_workspace_owner"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- Workspace already has a verification: This workspace has a verification already.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Workspace already has a verification"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "already_submitted"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "Workspace already has a verification",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "already_submitted"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Sending profile not created: With `purchaseNewNumber`, the sending profile could not be created.\n- Failed to inherit verification: The verification could not be copied.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` is the sentence the profile service gave, or `Failed to create messaging profile`.",
                      "title": "Sending profile not created",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to inherit verification"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to inherit verification",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/verification/submit": {
      "post": {
        "operationId": "submitEnterpriseWorkspaceVerification",
        "summary": "Submit a workspace's verification",
        "description": "For a workspace with no verification: creates a sending profile and the verification, buys a toll-free number and submits the verification for it when the opt-in image URLs and registration number allow. That costs money. For a workspace whose verification was rejected or is waiting for changes: updates the stored record with the fields sent and resubmits it. Sends a `verification.submitted` enterprise webhook for a first submission.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "submitVerification"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The business details.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "businessName": {
                    "type": "string"
                  },
                  "doingBusinessAs": {
                    "type": "string"
                  },
                  "website": {
                    "type": "string"
                  },
                  "address": {
                    "type": "object",
                    "properties": {
                      "street": {
                        "type": "string"
                      },
                      "address1": {
                        "type": "string",
                        "description": "Read when `street` is absent."
                      },
                      "address2": {
                        "type": "string"
                      },
                      "city": {
                        "type": "string"
                      },
                      "state": {
                        "type": "string",
                        "description": "A state name or its two-letter code."
                      },
                      "zip": {
                        "type": "string"
                      },
                      "country": {
                        "type": "string",
                        "description": "An ISO country code. Defaults to `US`."
                      }
                    },
                    "required": [
                      "city",
                      "state",
                      "zip"
                    ],
                    "description": "The business address. `street` or `address1` is required."
                  },
                  "contact": {
                    "type": "object",
                    "properties": {
                      "firstName": {
                        "type": "string"
                      },
                      "lastName": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "phone": {
                        "type": "string",
                        "description": "In E.164 format."
                      }
                    },
                    "required": [
                      "firstName",
                      "lastName",
                      "email",
                      "phone"
                    ]
                  },
                  "brn": {
                    "type": "string",
                    "description": "The business registration number, such as an EIN."
                  },
                  "brnType": {
                    "type": "string",
                    "description": "Such as `EIN`."
                  },
                  "brnCountry": {
                    "type": "string",
                    "description": "Defaults to `US`."
                  },
                  "entityType": {
                    "type": "string"
                  },
                  "useCase": {
                    "type": "string",
                    "description": "The messaging use case, such as `Appointments`."
                  },
                  "useCaseSummary": {
                    "type": "string"
                  },
                  "sampleMessages": {
                    "type": "string"
                  },
                  "optInWorkflow": {
                    "type": "string",
                    "description": "How recipients agree to receive messages."
                  },
                  "optInImageUrls": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ],
                    "description": "Public URLs showing the opt-in, as a list or comma separated."
                  },
                  "monthlyVolume": {
                    "type": "string",
                    "description": "Defaults to `1,000`."
                  },
                  "additionalInformation": {
                    "type": "string"
                  },
                  "ageGatedContent": {
                    "type": "boolean"
                  },
                  "privacyUrl": {
                    "type": "string"
                  },
                  "termsUrl": {
                    "type": "string"
                  },
                  "verification": {
                    "type": "object",
                    "properties": {
                      "businessName": {
                        "type": "string"
                      },
                      "doingBusinessAs": {
                        "type": "string"
                      },
                      "website": {
                        "type": "string"
                      },
                      "address": {
                        "type": "object",
                        "properties": {
                          "street": {
                            "type": "string"
                          },
                          "address1": {
                            "type": "string",
                            "description": "Read when `street` is absent."
                          },
                          "address2": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "state": {
                            "type": "string",
                            "description": "A state name or its two-letter code."
                          },
                          "zip": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string",
                            "description": "An ISO country code. Defaults to `US`."
                          }
                        },
                        "required": [
                          "city",
                          "state",
                          "zip"
                        ],
                        "description": "The business address. `street` or `address1` is required."
                      },
                      "contact": {
                        "type": "object",
                        "properties": {
                          "firstName": {
                            "type": "string"
                          },
                          "lastName": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "phone": {
                            "type": "string",
                            "description": "In E.164 format."
                          }
                        },
                        "required": [
                          "firstName",
                          "lastName",
                          "email",
                          "phone"
                        ]
                      },
                      "brn": {
                        "type": "string",
                        "description": "The business registration number, such as an EIN."
                      },
                      "brnType": {
                        "type": "string",
                        "description": "Such as `EIN`."
                      },
                      "brnCountry": {
                        "type": "string",
                        "description": "Defaults to `US`."
                      },
                      "entityType": {
                        "type": "string"
                      },
                      "useCase": {
                        "type": "string",
                        "description": "The messaging use case, such as `Appointments`."
                      },
                      "useCaseSummary": {
                        "type": "string"
                      },
                      "sampleMessages": {
                        "type": "string"
                      },
                      "optInWorkflow": {
                        "type": "string",
                        "description": "How recipients agree to receive messages."
                      },
                      "optInImageUrls": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ],
                        "description": "Public URLs showing the opt-in, as a list or comma separated."
                      },
                      "monthlyVolume": {
                        "type": "string",
                        "description": "Defaults to `1,000`."
                      },
                      "additionalInformation": {
                        "type": "string"
                      },
                      "ageGatedContent": {
                        "type": "boolean"
                      },
                      "privacyUrl": {
                        "type": "string"
                      },
                      "termsUrl": {
                        "type": "string"
                      }
                    },
                    "description": "A resubmission may wrap its fields in `verification`, as `POST /api/v1/enterprise/workspaces/provision` does. Top-level fields win."
                  }
                },
                "required": [
                  "businessName",
                  "website",
                  "address",
                  "contact",
                  "useCase",
                  "useCaseSummary",
                  "sampleMessages",
                  "optInWorkflow"
                ],
                "description": "A first submission needs every required field. Resubmitting a rejected verification, or one waiting for changes, takes any subset: a field left out keeps its stored value."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- Verification resubmitted: The verification was updated and resubmitted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "verification": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "The verification's id."
                        },
                        "userId": {
                          "type": "string",
                          "description": "The id of the user who owns it."
                        },
                        "organizationId": {
                          "type": "string",
                          "description": "The workspace's id."
                        },
                        "verificationType": {
                          "type": "string",
                          "description": "What the verification covers. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "toll_free",
                            "international",
                            "both"
                          ]
                        },
                        "region": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "businessName": {
                          "type": "string"
                        },
                        "doingBusinessAs": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "website": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "address1": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "address2": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "city": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "state": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The full state name."
                        },
                        "zip": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "addressCountry": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "contactFirstName": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "contactLastName": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "contactEmail": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "contactPhone": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "monthlyVolume": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "useCase": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "useCaseSummary": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "sampleMessages": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "optInWorkflow": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "optInImageUrls": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "As sent: one URL or several comma separated. URLs sent as a list are stored in the database's array form, as `{\"https://...\"}`."
                        },
                        "optInPageId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "optInSource": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "privacyPageId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "termsPageId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "usesHostedLegalPages": {
                          "type": [
                            "boolean",
                            "null"
                          ]
                        },
                        "ageGatedContent": {
                          "type": [
                            "boolean",
                            "null"
                          ]
                        },
                        "privacyUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "termsUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "brn": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "brnType": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "brnCountry": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "entityType": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "brnDocumentUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "isvReseller": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "additionalInformation": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "alphaSenderId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "numberPoolStickyEnabled": {
                          "type": "boolean"
                        },
                        "numberPoolGeomatchEnabled": {
                          "type": "boolean"
                        },
                        "tollFreeNumber": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "tollFreeNumberId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "description": "The verification's status as stored, not the public form `GET /verification` gives: `waiting_for_customer` here is `action_required` there, and `waiting_for_vendor` (and one more internal waiting status) is `processing` there. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `waiting_for_vendor`, `waiting_for_customer`, `verified`, `rejected`, `archived`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "pending",
                            "pending_review",
                            "submitted",
                            "in_progress",
                            "waiting_for_vendor",
                            "waiting_for_customer",
                            "verified",
                            "rejected",
                            "archived"
                          ]
                        },
                        "rejectionReason": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "previousRejectionReason": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "submissionCount": {
                          "type": "integer"
                        },
                        "messagingTermsAcceptedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "When the messaging terms were accepted. ISO 8601, in UTC."
                        },
                        "messagingTermsVersion": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "verificationScore": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "verificationChecks": {},
                        "verificationRanAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "When the automated checks last ran. ISO 8601, in UTC."
                        },
                        "riskLevel": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "role": {
                          "type": "string"
                        },
                        "inheritedFromVerificationId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "einDocR2Key": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "oldNumberDisposition": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the verification was created. ISO 8601, in UTC."
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the verification last changed. ISO 8601, in UTC."
                        }
                      },
                      "required": [
                        "id",
                        "userId",
                        "organizationId",
                        "verificationType",
                        "region",
                        "businessName",
                        "doingBusinessAs",
                        "website",
                        "address1",
                        "address2",
                        "city",
                        "state",
                        "zip",
                        "addressCountry",
                        "contactFirstName",
                        "contactLastName",
                        "contactEmail",
                        "contactPhone",
                        "monthlyVolume",
                        "useCase",
                        "useCaseSummary",
                        "sampleMessages",
                        "optInWorkflow",
                        "optInImageUrls",
                        "optInPageId",
                        "optInSource",
                        "privacyPageId",
                        "termsPageId",
                        "usesHostedLegalPages",
                        "ageGatedContent",
                        "privacyUrl",
                        "termsUrl",
                        "brn",
                        "brnType",
                        "brnCountry",
                        "entityType",
                        "brnDocumentUrl",
                        "isvReseller",
                        "additionalInformation",
                        "alphaSenderId",
                        "numberPoolStickyEnabled",
                        "numberPoolGeomatchEnabled",
                        "tollFreeNumber",
                        "tollFreeNumberId",
                        "status",
                        "rejectionReason",
                        "previousRejectionReason",
                        "submissionCount",
                        "messagingTermsAcceptedAt",
                        "messagingTermsVersion",
                        "verificationScore",
                        "verificationRanAt",
                        "riskLevel",
                        "role",
                        "inheritedFromVerificationId",
                        "einDocR2Key",
                        "oldNumberDisposition",
                        "createdAt",
                        "updatedAt"
                      ],
                      "description": "The whole stored verification record, internal fields included, among them two of the carrier's own ids that are not listed here.",
                      "title": "Stored verification record"
                    },
                    "message": {
                      "type": "string",
                      "enum": [
                        "Verification resubmitted successfully"
                      ]
                    },
                    "updateType": {
                      "type": "string",
                      "enum": [
                        "resubmit"
                      ]
                    },
                    "submissionCount": {
                      "type": "integer"
                    },
                    "previousRejectionReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "success",
                    "verification",
                    "message",
                    "updateType",
                    "submissionCount",
                    "previousRejectionReason"
                  ],
                  "title": "Verification resubmitted"
                },
                "examples": {
                  "resubmit": {
                    "summary": "Built from the handler: a rejected verification resubmitted with a new opt-in image. The real record also carries two of the carrier's own ids, left out here.",
                    "value": {
                      "success": true,
                      "verification": {
                        "id": "00000000-0000-4000-8000-000000000103",
                        "userId": "user_placeholder1",
                        "organizationId": "00000000-0000-4000-8000-000000000101",
                        "verificationType": "toll_free",
                        "region": "us",
                        "businessName": "Acme Dental",
                        "doingBusinessAs": null,
                        "website": "https://acme-dental.example.com",
                        "address1": "100 Main St",
                        "address2": null,
                        "city": "Austin",
                        "state": "Texas",
                        "zip": "78701",
                        "addressCountry": "US",
                        "contactFirstName": "Ada",
                        "contactLastName": "Lovelace",
                        "contactEmail": "ada@example.com",
                        "contactPhone": "+15555550143",
                        "monthlyVolume": "1,000",
                        "useCase": "Appointments",
                        "useCaseSummary": "Appointment reminders for patients.",
                        "sampleMessages": "Acme Dental: your cleaning is tomorrow at 10am. Reply STOP to opt out.",
                        "optInWorkflow": "Patients opt in on the booking form.",
                        "optInImageUrls": "https://acme-dental.example.com/opt-in-v2.png",
                        "optInPageId": null,
                        "optInSource": "manual",
                        "privacyPageId": null,
                        "termsPageId": null,
                        "usesHostedLegalPages": false,
                        "ageGatedContent": false,
                        "privacyUrl": null,
                        "termsUrl": null,
                        "brn": "12-3456789",
                        "brnType": "EIN",
                        "brnCountry": "US",
                        "entityType": "PRIVATE_PROFIT",
                        "brnDocumentUrl": null,
                        "isvReseller": "Sendly",
                        "additionalInformation": null,
                        "alphaSenderId": null,
                        "numberPoolStickyEnabled": true,
                        "numberPoolGeomatchEnabled": false,
                        "tollFreeNumber": "+15555550142",
                        "tollFreeNumberId": "number_placeholder1",
                        "status": "submitted",
                        "rejectionReason": null,
                        "previousRejectionReason": "Opt-in image does not show the disclosure.",
                        "submissionCount": 2,
                        "messagingTermsAcceptedAt": "2026-10-01T09:30:00.000Z",
                        "messagingTermsVersion": "v1.0",
                        "verificationScore": 4,
                        "verificationChecks": null,
                        "verificationRanAt": null,
                        "riskLevel": "low",
                        "role": "active",
                        "inheritedFromVerificationId": null,
                        "einDocR2Key": null,
                        "oldNumberDisposition": null,
                        "createdAt": "2026-10-01T09:30:00.000Z",
                        "updatedAt": "2026-10-03T12:00:00.000Z"
                      },
                      "message": "Verification resubmitted successfully",
                      "updateType": "resubmit",
                      "submissionCount": 2,
                      "previousRejectionReason": "Opt-in image does not show the disclosure."
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Created.\n\n- Verification created: The verification was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "verificationId": {
                      "type": "string",
                      "description": "The verification's id."
                    },
                    "status": {
                      "type": "string",
                      "description": "`submitted` when a number was bought and the verification sent for review; `pending` otherwise. Known values: `pending`, `submitted`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "pending",
                        "submitted"
                      ]
                    },
                    "tollFreeNumber": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The workspace's toll-free number in E.164 format, or `null` before one is set."
                    },
                    "businessName": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "verificationId",
                    "status",
                    "tollFreeNumber",
                    "businessName"
                  ],
                  "title": "Verification created"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: a first submission, number bought and submitted.",
                    "value": {
                      "verificationId": "00000000-0000-4000-8000-000000000103",
                      "status": "submitted",
                      "tollFreeNumber": "+15555550142",
                      "businessName": "Acme Dental"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- Missing required fields: businessName, website, address, contact, useCase, useCaseSummary, sampleMessages, optInWorkflow: A first submission lacks a required field.\n- address must include street, city, state, zip: A first submission's address lacks a part.\n- contact must include firstName, lastName, email, phone: A first submission's contact lacks a part.\n- Missing required fields, after merging: A resubmission still lacks a required field once the stored values fill the gaps.\n- Invalid useCase: A resubmission's `useCase` is not one the carrier accepts.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Missing required fields: businessName, website, address, contact, useCase, useCaseSummary, sampleMessages, optInWorkflow"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Missing required fields: businessName, website, address, contact, useCase, useCaseSummary, sampleMessages, optInWorkflow",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "address must include street, city, state, zip"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "address must include street, city, state, zip",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "contact must include firstName, lastName, email, phone"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "contact must include firstName, lastName, email, phone",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "missing": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "hint": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error",
                        "missing",
                        "hint"
                      ],
                      "description": "`error` names the fields, as `Missing required fields: website, useCase`.",
                      "title": "Missing required fields, after merging",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "valid": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_request"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error",
                        "valid"
                      ],
                      "description": "`error` names the value and lists every valid one.",
                      "title": "Invalid useCase",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_request"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- Workspace already has a verification: The workspace has a verification that is neither rejected nor waiting for changes. `status` is the stored status.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Workspace already has a verification"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "description": "The verification's status as stored, not the public form `GET /verification` gives: `waiting_for_customer` here is `action_required` there, and `waiting_for_vendor` (and one more internal waiting status) is `processing` there. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `waiting_for_vendor`, `waiting_for_customer`, `verified`, `rejected`, `archived`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "pending",
                        "pending_review",
                        "submitted",
                        "in_progress",
                        "waiting_for_vendor",
                        "waiting_for_customer",
                        "verified",
                        "rejected",
                        "archived"
                      ]
                    },
                    "sendlyCode": {
                      "type": "string",
                      "enum": [
                        "already_submitted"
                      ],
                      "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                    }
                  },
                  "required": [
                    "error",
                    "status"
                  ],
                  "title": "Workspace already has a verification",
                  "x-sendly-error-shape": "sentence",
                  "x-sendly-error-codes": [],
                  "x-sendly-proposed-codes": [
                    "already_submitted"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Sending profile not created: A first submission's sending profile could not be created.\n- Failed to submit verification: The verification could not be saved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` is the sentence the profile service gave, or `Failed to create messaging profile`.",
                      "title": "Sending profile not created",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to submit verification"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to submit verification",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/webhooks": {
      "get": {
        "operationId": "listEnterpriseWorkspaceWebhooks",
        "summary": "List a workspace's webhooks",
        "description": "Lists every webhook of the workspace, newest first, as a bare array.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "listWebhooks"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The webhooks.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "The webhook's id."
                      },
                      "url": {
                        "type": "string"
                      },
                      "events": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "isActive": {
                        "type": "boolean"
                      },
                      "createdAt": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the webhook was created. ISO 8601, in UTC."
                      }
                    },
                    "required": [
                      "id",
                      "url",
                      "events",
                      "isActive",
                      "createdAt"
                    ]
                  }
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: one webhook.",
                    "value": [
                      {
                        "id": "whk_placeholder1",
                        "url": "https://example.com/sendly-webhooks",
                        "events": [
                          "message.sent",
                          "message.delivered",
                          "message.failed"
                        ],
                        "isActive": true,
                        "createdAt": "2026-10-01T09:30:00.000Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to list webhooks: The webhooks could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to list webhooks"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to list webhooks",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "setEnterpriseWorkspaceWebhook",
        "summary": "Set a workspace's webhook",
        "description": "Creates the workspace's webhook, or when it has one, changes the newest one's URL, events and description.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "setWebhook"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The webhook.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "Where deliveries go. Any URL that parses."
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "The events to deliver. Defaults to `message.sent`, `message.delivered` and `message.failed`, also when updating."
                  },
                  "description": {
                    "type": "string",
                    "description": "A note kept with the webhook. Left out, it is cleared."
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- Webhook updated: The workspace's newest webhook was changed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The webhook's id."
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "updated": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "events",
                    "updated"
                  ],
                  "title": "Webhook updated"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the existing webhook changed.",
                    "value": {
                      "id": "whk_placeholder1",
                      "url": "https://example.com/sendly-webhooks-v2",
                      "events": [
                        "message.delivered"
                      ],
                      "updated": true
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Created.\n\n- Webhook created: The workspace had no webhook, so one was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The webhook's id."
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "secret": {
                      "type": "string",
                      "description": "The signing secret. Shown only now: store it to verify deliveries."
                    },
                    "created": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "events",
                    "secret",
                    "created"
                  ],
                  "title": "Webhook created"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the workspace's first webhook, with its secret.",
                    "value": {
                      "id": "whk_placeholder1",
                      "url": "https://example.com/sendly-webhooks",
                      "events": [
                        "message.sent",
                        "message.delivered",
                        "message.failed"
                      ],
                      "secret": "whsec_placeholder1",
                      "created": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- url is required: `url` is missing or not a string.\n- Invalid URL: `url` does not parse as a URL.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "url is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "url is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Invalid URL"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "invalid_url"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Invalid URL",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "invalid_url"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to set webhook: The webhook could not be saved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to set webhook"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to set webhook",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteEnterpriseWorkspaceWebhooks",
        "summary": "Delete a workspace's webhooks",
        "description": "Deletes one webhook of the workspace, or every one when `webhookId` is left out. Answers the same whether or not anything matched.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "deleteWebhooks"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The one webhook to delete."
            },
            "required": false,
            "name": "webhookId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The webhooks are gone, if there were any.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler.",
                    "value": {
                      "success": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to delete webhook: The webhooks could not be deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to delete webhook"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to delete webhook",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enterprise/workspaces/{workspaceId}/webhooks/test": {
      "post": {
        "operationId": "testEnterpriseWorkspaceWebhook",
        "summary": "Test a workspace's webhook",
        "description": "Sends a `webhook.test` event to the workspace's newest webhook and reports how it went. A failed delivery still answers 200, with `success: false`.",
        "tags": [
          "Enterprise workspaces"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "enterprise.workspaces",
          "method": "testWebhook"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. It must be a team workspace the key's owner owns."
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EnterpriseWorkspaceWebhookTestResult: The test was attempted, or could not be.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseWorkspaceWebhookTestResult"
                },
                "examples": {
                  "default": {
                    "summary": "Built from sendTestWebhook: the endpoint accepted the test event.",
                    "value": {
                      "success": true,
                      "message": "Test webhook delivered successfully in 120ms",
                      "delivery": {
                        "id": "delivery_placeholder1",
                        "delivery_id": "delivery_placeholder1",
                        "webhook_url": "https://example.com/sendly-webhooks",
                        "event_type": "webhook.test",
                        "status": "delivered",
                        "response_time": 120,
                        "status_code": 200,
                        "response_body": "ok",
                        "delivered_at": "2026-10-03T12:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `enterprise_required`, `enterprise_inactive`: The key is not an enterprise master key (`enterprise_required`), or its enterprise account is not active (`enterprise_inactive`).\n- `invalid_workspace`, `not_workspace_owner`: The workspace is a personal one (`invalid_workspace`), or the key's owner does not own it (`not_workspace_owner`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/EnterpriseRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceNotOwnedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that is not an enterprise master key, refused before anything runs.",
                    "value": {
                      "error": "enterprise_required",
                      "message": "This endpoint requires an enterprise master API key. Create one from the dashboard."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.\n- No webhook configured for this workspace: The workspace has no webhook.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "No webhook configured for this workspace"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "webhook_not_configured"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "No webhook configured for this workspace",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "webhook_not_configured"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Failed to test webhook: The workspace's webhooks could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Failed to test webhook"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "internal_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "Failed to test webhook",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "internal_error"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/events": {
      "get": {
        "operationId": "streamEvents",
        "summary": "Stream real-time events",
        "description": "Opens a Server-Sent Events stream of the workspace's real-time events: new messages, delivery statuses, conversation, credit, batch, campaign and webhook delivery updates, and more. The connection stays open until the client closes it. The route mounts no rate limiter: opening a stream is not counted against the key's limit, and nothing limits how many streams a key holds open.",
        "tags": [
          "Events"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated event types to send, such as `new_message,message_status`, each matched exactly, with no trimming of spaces. An event of any other type is still taken off the queue, and is dropped. Every type is sent when this is absent or empty. Pass it once, as one value. Known types: `new_message`, `message_status`, `conversation_update`, `credit_update`, `batch_progress`, `campaign_status`, `webhook_delivery`, `webhook_recovery_progress`, `verification_status`, `port_request_update`, `number_update`, `number_message`, `tendlc_update`, `rcs_update`, `hold_update`, `invitation_update`, `member_update`, `organization_update`, `incoming_call`, `call_update`, `voice_update`, `enterprise_workspace_update`, `enterprise_credit_update`, `enterprise_message_update`, `enterprise_audit_update`, `enterprise_verification_update`."
            },
            "required": false,
            "name": "types",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- EventStream: The stream opened. The status and headers are sent at once, with `Cache-Control: no-cache` and `X-Accel-Buffering: no`.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "$ref": "#/components/schemas/EventStream"
                },
                "examples": {
                  "default": {
                    "summary": "The first 3 seconds of a stream.",
                    "value": ": connected\n\ndata: {\"type\":\"new_message\",\"data\":{\"id\":\"00000000-0000-4000-8000-000000000001\",\"to\":\"+15555550100\",\"from\":\"SENDLY-TEST\",\"text\":\"Your Sendly code is 123456\",\"status\":\"delivered\",\"direction\":\"outbound\"},\"timestamp\":1790986437498}\n\n"
                  },
                  "types-filter": {
                    "summary": "The first 3 seconds of a stream of message_status events only.",
                    "value": ": connected\n\n"
                  },
                  "with-events": {
                    "summary": "The first 7 seconds of a stream opened just after a test key's simulated SMS, which queues its events.",
                    "value": ": connected\n\ndata: {\"type\":\"conversation_update\",\"data\":{\"conversationId\":\"00000000-0000-4000-8000-000000000002\",\"status\":\"active\"},\"timestamp\":1790986437525}\n\ndata: {\"type\":\"new_message\",\"data\":{\"id\":\"00000000-0000-4000-8000-000000000003\",\"to\":\"+15555550100\",\"from\":\"SENDLY-TEST\",\"text\":\"Your Sendly code is 123456\",\"status\":\"delivered\",\"direction\":\"outbound\"},\"timestamp\":1790986445118}\n\ndata: {\"type\":\"conversation_update\",\"data\":{\"conversationId\":\"00000000-0000-4000-8000-000000000002\",\"status\":\"active\"},\"timestamp\":1790986445145}\n\n"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key passed in the URL.",
                    "value": {
                      "error": "invalid_request",
                      "message": "API keys must not be passed in URL parameters. Use the Authorization header instead."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  },
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/labels": {
      "get": {
        "operationId": "listLabels",
        "summary": "List labels",
        "description": "Lists every label of the key's workspace, sorted by name in ascending order, with no paging. A key without a workspace lists the labels of its owner's personal account.",
        "tags": [
          "Labels"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "labels",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- LabelList: Every label, sorted by name.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LabelList"
                },
                "examples": {
                  "default": {
                    "summary": "The workspace's labels, sorted by name.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "userId": "00000000-0000-4000-8000-000000000002",
                          "organizationId": null,
                          "name": "contract-capture-629268bf",
                          "color": "#2563eb",
                          "description": "Customers to call back first.",
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000003",
                          "userId": "00000000-0000-4000-8000-000000000002",
                          "organizationId": null,
                          "name": "contract-capture-629268bf-plain",
                          "color": "#6b7280",
                          "description": null,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `conversations_api` flag is off for the key's owner, or could not be evaluated. Answered before anything else the handler does.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createLabel",
        "summary": "Create a label",
        "description": "Creates a label in the key's workspace. Label names are unique within a workspace, compared exactly, so `VIP` and `vip` are two labels.",
        "tags": [
          "Labels"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "labels",
          "method": "create"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "requestBody": {
          "description": "The label to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLabelRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- Label: The label was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Label"
                },
                "examples": {
                  "defaults": {
                    "summary": "A label with only a name: the default color, and no description.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000003",
                      "userId": "00000000-0000-4000-8000-000000000002",
                      "organizationId": null,
                      "name": "contract-capture-629268bf-plain",
                      "color": "#6b7280",
                      "description": null,
                      "createdAt": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "default": {
                    "summary": "A label with a name, a color and a description.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "userId": "00000000-0000-4000-8000-000000000002",
                      "organizationId": null,
                      "name": "contract-capture-629268bf",
                      "color": "#2563eb",
                      "description": "Customers to call back first.",
                      "createdAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `name` is missing, empty or not a string.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The name is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "name is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `conversations_api` flag is off for the key's owner, or could not be evaluated. Answered before anything else the handler does.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `conflict`: The workspace already has a label with this name.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "conflict"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "conflict",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "conflict"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A name the workspace already has a label with.",
                    "value": {
                      "error": "conflict",
                      "message": "Label with this name already exists"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: Storing the label failed. `message` is the database's own error text, such as for a `name` that holds a NUL character.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "nul-in-name": {
                    "summary": "A name holding a NUL character, which the database refuses.",
                    "value": {
                      "error": "internal_error",
                      "message": "invalid byte sequence for encoding \"UTF8\": 0x00"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/labels/{id}": {
      "delete": {
        "operationId": "deleteLabel",
        "summary": "Delete a label",
        "description": "Deletes a label of the key's workspace and removes it from every conversation and message. An id that names no label of the workspace answers 204 too, and deletes nothing.",
        "tags": [
          "Labels"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "labels",
          "method": "delete"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The label's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.\n\n- The label was deleted, or no label of the workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `conversations_api` flag is off for the key's owner, or could not be evaluated. Answered before anything else the handler does.\n- `not_found`: The id is empty or holds a NUL character.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/links": {
      "get": {
        "operationId": "listShortLinks",
        "summary": "List short links",
        "description": "Lists the workspace's short links, newest first, with their clicks: those minted with `POST /api/v1/links` or in the dashboard, and those made by shortening the links in sent messages. The key needs `links:read`. A key that holds neither `links:read` nor `links:write`, such as one made before they existed, can use `sms:read` instead. Behind the `url_shortener` flag, which is evaluated for the key's owner. Until it is on, every call with a key that has the operation's scope answers 404 `{ \"error\": \"not_found\" }`. A path the server does not have answers 404 `{ \"error\": \"Not found\" }` instead, so the two can be told apart.",
        "tags": [
          "Short links"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "top-level-total",
        "x-sendly-sdk": {
          "resource": "links",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "Page size, 1 to 200. Defaults to 50, which is also what a value that is not a number gives. A value below 1 is raised to 1, and one above 200 is lowered to 200."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many links to skip. Defaults to 0, which is also what a negative value or one that is not a number gives."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ShortLinkList: A page of links, and how many the workspace has in all.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortLinkList"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and service code, not captured: the throwaway test key belongs to no workspace, so production answers 400 workspace_required before listing. The shape is listShortLinks' return value.",
                    "value": {
                      "links": [
                        {
                          "code": "Ab3xY7",
                          "shortUrl": "https://sendly.live/l/acme/Ab3xY7",
                          "destinationUrl": "https://example.com/spring-sale?utm_source=sms",
                          "brandSlug": "acme",
                          "clickCount": 3,
                          "disabled": false,
                          "lastCountry": "US",
                          "lastClickedAt": "2026-01-01T00:00:00.000Z",
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "spark": [
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            1,
                            0,
                            2
                          ]
                        },
                        {
                          "code": "Kp7mQ2",
                          "shortUrl": "https://sendly.live/l/Kp7mQ2",
                          "destinationUrl": "https://example.com/welcome",
                          "brandSlug": null,
                          "clickCount": 0,
                          "disabled": true,
                          "lastCountry": null,
                          "lastClickedAt": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "spark": [
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0,
                            0
                          ]
                        }
                      ],
                      "total": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The key belongs to no workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that belongs to no workspace.",
                    "value": {
                      "error": "workspace_required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `insufficient_permissions`: The key lacks `links:read`. A key that holds neither links scope, such as one made before they existed, passes with `sms:read` instead.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `messages:read` permission for short links. The workspace owner always has it.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Short links are not enabled for the key's owner.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and service code, not captured: the throwaway test key belongs to no workspace, so production answers 400 workspace_required before the flag check. The url_shortener flag is off for the key's owner.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The flag or the caller's role could not be checked.\n- `internal_error`: The links could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createShortLink",
        "summary": "Create a short link",
        "description": "Mints a short link to a URL, with the workspace's brand slug when it has one. Every call mints a new link, even for a URL that already has one, unless it repeats an `Idempotency-Key`. Only a live API key of a workspace with an approved business verification can mint, and a workspace can mint 1,000 links a UTC day, counting the links made by shortening sent messages. The key needs `links:write`. A key that holds neither `links:read` nor `links:write`, such as one made before they existed, can use `sms:send` instead. Behind the `url_shortener` flag, which is evaluated for the key's owner. Until it is on, every call with a key that has the operation's scope answers 404 `{ \"error\": \"not_found\" }`. A path the server does not have answers 404 `{ \"error\": \"Not found\" }` instead, so the two can be told apart.",
        "tags": [
          "Short links"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "links",
          "method": "create"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The URL to shorten.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "pattern": "^https?:\\/\\/",
                    "description": "The destination: an absolute `http` or `https` URL, written `http://` or `https://` and then the host, of at most 2,048 characters once serialised. Spaces around it are trimmed. A URL with a user name or password (`https://a@b.example`), a backslash, a percent-encoded or dot-ended host, or a space, control or invisible character in it is refused, because a reader, a checker and a browser could take it to different sites."
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ShortLink: The link was minted. The answer is 200, not 201.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortLink"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and service code, not captured: the throwaway test key belongs to no workspace, so production answers 400 workspace_required before minting, and minting would store a real link. The shape is createShortLink's return value.",
                    "value": {
                      "code": "Ab3xY7",
                      "shortUrl": "https://sendly.live/l/acme/Ab3xY7",
                      "destinationUrl": "https://example.com/spring-sale?utm_source=sms"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The key belongs to no workspace.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_url`: `url` is missing, not a string, not an absolute `http` or `https` URL, or written in a form that could be read as more than one site: a user name or password, a backslash, a percent-encoded or dot-ended host, or a space, control or invisible character.\n- `already_short`: `url` is already a Sendly short link, in any of its forms.\n- `destination_too_long`: `url` is longer than 2,048 characters.\n- `link_destination_not_allowed`: `url` is a public shortener's link, is on a site Sendly does not allow, or a threat check flagged it.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "$ref": "#/components/schemas/ShortLinkInvalidUrlError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "already_short"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "already_short",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "already_short"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "destination_too_long"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "destination_too_long",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "destination_too_long"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "link_destination_not_allowed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "reason": {
                          "type": "string",
                          "enum": [
                            "public_shortener",
                            "blocked_host",
                            "unsafe_destination"
                          ],
                          "description": "Why: `public_shortener` for a link from a public shortener, `blocked_host` for a site Sendly does not allow, `unsafe_destination` for a site a threat check flagged."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "reason"
                      ],
                      "title": "link_destination_not_allowed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "link_destination_not_allowed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-url": {
                    "summary": "Built from the handler and service code, not captured: the throwaway test key belongs to no workspace, so production answers 400 workspace_required before the URL check. The url is not an absolute URL, which is checked before the key type, so a test key gets this answer too.",
                    "value": {
                      "error": "invalid_url",
                      "message": "Enter a valid http(s) URL."
                    }
                  },
                  "default": {
                    "summary": "A test key that belongs to no workspace. The url is not a URL, so nothing could be minted.",
                    "value": {
                      "error": "workspace_required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `insufficient_permissions`: The key lacks `links:write`. A key that holds neither links scope, such as one made before they existed, passes with `sms:send` instead.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `messages:send` permission for short links. The workspace owner always has it.\n- `live_key_required`: A test key or a CLI session called it.\n- `business_verification_required`: The workspace has no approved business verification, toll-free or 10DLC.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "business_verification_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "verificationUrl": {
                          "type": "string",
                          "description": "The dashboard page where the workspace verifies its business."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "verificationUrl"
                      ],
                      "title": "business_verification_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "business_verification_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Short links are not enabled for the key's owner.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `daily_link_limit_reached`: The workspace has created 1,000 links since midnight UTC. `Retry-After` gives the seconds until then.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "daily_link_limit_reached"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "limit": {
                          "type": "integer",
                          "description": "New links a workspace may create in a UTC day: 1,000."
                        },
                        "resetsAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "The next midnight UTC, when the count starts again. ISO 8601, in UTC."
                        },
                        "retryAfter": {
                          "type": "integer",
                          "description": "Seconds until `resetsAt`."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "limit",
                        "resetsAt",
                        "retryAfter"
                      ],
                      "title": "daily_link_limit_reached",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "daily_link_limit_reached"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The flag or the caller's role could not be checked.\n- `internal_error`: The link could not be stored, as when five codes in a row were already taken.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `short_links_disabled`: Sendly has turned short links off for everyone for now.\n- `link_screening_unavailable`: The threat check could not answer for `url` just now, so nothing was minted. Try again shortly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_links_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "short_links_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_links_disabled"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "link_screening_unavailable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "link_screening_unavailable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "link_screening_unavailable"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/links/{code}": {
      "patch": {
        "operationId": "setShortLinkDisabled",
        "summary": "Turn a short link off or on",
        "description": "Switches one of the workspace's short links off, so its redirect answers 410, or back on. Only a live API key can, and in a team workspace only an owner or admin. A link Sendly switched off stays off. The key needs `links:write`. A key that holds neither `links:read` nor `links:write`, such as one made before they existed, can use `sms:send` instead. Behind the `url_shortener` flag, which is evaluated for the key's owner. Until it is on, every call with a key that has the operation's scope answers 404 `{ \"error\": \"not_found\" }`. A path the server does not have answers 404 `{ \"error\": \"Not found\" }` instead, so the two can be told apart.",
        "tags": [
          "Short links"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "links",
          "method": "setDisabled"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The link's code, matched exactly."
            },
            "required": true,
            "name": "code",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The state to set.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "disabled": {
                    "type": "boolean",
                    "description": "`true` switches the link off, `false` back on. Only a JSON boolean."
                  }
                },
                "required": [
                  "disabled"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ShortLinkDisabled: The link's new state. Setting the state it already had answers this too.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortLinkDisabled"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and service code, not captured: the throwaway test key belongs to no workspace, so production answers 400 workspace_required before the update. The shape is the row setShortLinkDisabled returns.",
                    "value": {
                      "code": "Ab3xY7",
                      "disabled": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The key belongs to no workspace.\n- `disabled_boolean_required`: `disabled` is missing or not a boolean.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "disabled_boolean_required"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "disabled_boolean_required",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "disabled_boolean_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key that belongs to no workspace, for a code that matches no link and a body that is not a boolean.",
                    "value": {
                      "error": "workspace_required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: A team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `insufficient_permissions`: The key lacks `links:write`. A key that holds neither links scope, such as one made before they existed, passes with `sms:send` instead.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission for short links. The workspace owner always has it.\n- `live_key_required`: A test key or a CLI session called it.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Short links are not enabled for the key's owner.\n- `link_not_found`: The workspace has no link with this code.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "link_not_found"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "title": "link_not_found",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "link_not_found"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and service code, not captured: the throwaway test key belongs to no workspace, so production answers 400 workspace_required before the lookup. No link in the workspace has this code.",
                    "value": {
                      "error": "link_not_found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `link_disabled_by_sendly`: `disabled` is `false`, but Sendly switched the link off, so the workspace cannot switch it back on.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "link_disabled_by_sendly"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "link_disabled_by_sendly",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "link_disabled_by_sendly"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The flag or the caller's role could not be checked.\n- `internal_error`: The link could not be updated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/media": {
      "get": {
        "operationId": "listMedia",
        "summary": "List media",
        "description": "Lists up to 100 of the newest uploaded images, newest first, with no paging. A personal key lists its owner's personal uploads; a workspace key lists every upload in the workspace, whoever made it.",
        "tags": [
          "Media"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- MediaList: The uploaded images, newest first. Empty when there are none.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaList"
                },
                "examples": {
                  "default": {
                    "summary": "The test account's one uploaded GIF.",
                    "value": {
                      "data": [
                        {
                          "id": "upload_placeholder1",
                          "url": "https://assets.sendly.live/sendly-mms/mms-media/00000000-0000-4000-8000-000000000001/00000000-0000-4000-8000-000000000002.gif",
                          "content_type": "image/gif",
                          "size_bytes": 29,
                          "filename": "pixel.gif",
                          "created_at": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `feature_disabled`: MMS is not enabled for the key owner's account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `server_error`: The uploads could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "uploadMedia",
        "summary": "Upload media",
        "description": "Stores one image for MMS and returns its public URL. A JPEG or PNG is turned upright and re-encoded; a GIF is stored as sent. A test key stores the file too: uploads are not simulated.",
        "tags": [
          "Media"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "media",
          "method": "upload"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "A multipart form with the image in its `file` field.",
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UploadMediaRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- UploadedMedia: The image was stored.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadedMedia"
                },
                "examples": {
                  "default": {
                    "summary": "A 1x1 GIF, stored as sent.",
                    "value": {
                      "id": "upload_placeholder1",
                      "url": "https://assets.sendly.live/sendly-mms/mms-media/00000000-0000-4000-8000-000000000001/00000000-0000-4000-8000-000000000002.gif",
                      "contentType": "image/gif",
                      "sizeBytes": 29
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_upload`: A file in a field other than `file`, more than one file, or a malformed body such as one without a boundary. It runs before the handler, so it answers before the MMS check. A body that is not multipart skips it.\n- `invalid_request`: No file arrived in `file`, as when the body is not multipart at all.\n- `invalid_file`: The file's bytes are not a JPEG, PNG or GIF image, whatever its part declared.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidUploadError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_file"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_file",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_file"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-file": {
                    "summary": "A part declared as a PNG whose bytes are text.",
                    "value": {
                      "error": "invalid_file",
                      "message": "File content does not match a supported image type (JPEG, PNG, GIF)"
                    }
                  },
                  "default": {
                    "summary": "A JSON body, so no file arrived.",
                    "value": {
                      "error": "invalid_request",
                      "message": "No file provided. Upload a JPEG, PNG, or GIF image."
                    }
                  },
                  "no-boundary": {
                    "summary": "Built from the code: since #234 the last error handler answers an upload middleware's refusal with a 4xx that says why, not a 500 `Internal Server Error`. The production capture of 2026-10-03 predates that change. It was: A multipart Content-Type with no boundary.",
                    "value": {
                      "error": "invalid_upload",
                      "message": "The multipart body could not be read."
                    }
                  },
                  "unexpected-field": {
                    "summary": "Built from the code: since #234 the last error handler answers an upload middleware's refusal with a 4xx that says why, not a 500 `Internal Server Error`. The production capture of 2026-10-03 predates that change. It was: The image in a field other than `file`.",
                    "value": {
                      "error": "invalid_upload",
                      "message": "Unexpected file field \"image\"."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `feature_disabled`: MMS is not enabled for the key owner's account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.\n- `file_too_large`: A file over 600 KB. It runs before the handler, so it answers before the MMS check.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyTooLargeError"
                    },
                    {
                      "$ref": "#/components/schemas/FileTooLargeError"
                    }
                  ]
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.\n- `unsupported_media_type`: A part in `file` declared as anything but `image/jpeg`, `image/png` or `image/gif` (`Only JPEG, PNG, and GIF images are allowed for MMS`). It runs before the handler, so it answers before the MMS check.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyEncodingError"
                    },
                    {
                      "$ref": "#/components/schemas/UnsupportedMediaTypeError"
                    }
                  ]
                },
                "examples": {
                  "wrong-type": {
                    "summary": "Built from the code: since #234 the last error handler answers an upload middleware's refusal with a 4xx that says why, not a 500 `Internal Server Error`. The production capture of 2026-10-03 predates that change. It was: A part declared as text/plain, refused by the upload middleware.",
                    "value": {
                      "error": "unsupported_media_type",
                      "message": "Only JPEG, PNG, and GIF images are allowed for MMS"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `upload_failed`: The image could not be processed or stored, as when its bytes start like an image but cannot be decoded.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "upload_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "upload_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "upload_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "undecodable": {
                    "summary": "Bytes that start like a GIF but cannot be decoded.",
                    "value": {
                      "error": "upload_failed",
                      "message": "Failed to upload media file"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/media/{id}": {
      "delete": {
        "operationId": "deleteMedia",
        "summary": "Delete media",
        "description": "Deletes an uploaded image and its stored file. Only a key created by the user who uploaded it can delete it: a workspace key created by another member gets a 404, though `GET /api/v1/media` lists the file for that key. A key of the same user in another workspace, or on the other side of personal and workspace, deletes the stored file and then answers 500.",
        "tags": [
          "Media"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The media file's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.\n\n- The image was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `feature_disabled`: MMS is not enabled for the key owner's account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No media file has this id, it was deleted already, it was uploaded by another user (even in the same workspace), or the id names an upload that is not MMS media.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "already-deleted": {
                    "summary": "The GIF deleted a moment ago, deleted again.",
                    "value": {
                      "error": "not_found",
                      "message": "Media not found"
                    }
                  },
                  "default": {
                    "summary": "An id that matches no media file.",
                    "value": {
                      "error": "not_found",
                      "message": "Media not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `server_error`: Deleting failed. A file the same user uploaded in another workspace, or with a personal key and deleted with a workspace key (or the other way round), answers this after its stored file is already gone, and stays listed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages": {
      "get": {
        "operationId": "listMessages",
        "summary": "List messages",
        "description": "Lists the workspace's messages, newest first. A test key lists only simulated messages; a live key lists live ones unless `sandbox` is `true`.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "offset",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "list"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size, 1 to 100. Defaults to 50, which is also what 0 or a value that is not a number gives. A value below 1 is raised to 1, and one above 100 is lowered to 100."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many messages to skip. Ignored when `page` is set."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "The page to return, starting at 1. Takes precedence over `offset`."
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only messages with this status."
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ],
              "description": "Only messages in this direction. Any other value is ignored."
            },
            "required": false,
            "name": "direction",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only messages to this phone number. A number without its leading `+` matches with it too."
            },
            "required": false,
            "name": "to",
            "in": "query"
          },
          {
            "schema": {
              "type": "boolean",
              "description": "Live keys only: `true` lists simulated messages instead of live ones. A test key always lists simulated messages."
            },
            "required": false,
            "name": "sandbox",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Full-text search over the message text, best match first."
            },
            "required": false,
            "name": "q",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- MessageList: A page of messages.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageList"
                },
                "examples": {
                  "default": {
                    "summary": "The two newest simulated messages.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000003",
                          "to": "+15005550001",
                          "from": "SENDLY-TEST",
                          "text": "Your Sendly code is 123456",
                          "status": "failed",
                          "direction": "outbound",
                          "error": "Invalid phone number",
                          "errorCode": null,
                          "retryCount": 0,
                          "segments": 1,
                          "creditsUsed": 0,
                          "isSandbox": true,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "deliveredAt": null,
                          "message_format": "sms",
                          "messageFormat": "sms"
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "to": "+15555550100",
                          "from": "SENDLY-TEST",
                          "text": "Your Sendly code is 123456",
                          "status": "delivered",
                          "direction": "outbound",
                          "error": null,
                          "errorCode": null,
                          "retryCount": 0,
                          "segments": 1,
                          "creditsUsed": 0,
                          "isSandbox": true,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "deliveredAt": "2026-01-01T00:00:00.000Z",
                          "message_format": "sms",
                          "messageFormat": "sms"
                        }
                      ],
                      "pagination": {
                        "total": 657,
                        "limit": 2,
                        "offset": 0,
                        "page": 1,
                        "totalPages": 329,
                        "hasMore": true
                      },
                      "count": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key passed in the URL.",
                    "value": {
                      "error": "invalid_request",
                      "message": "API keys must not be passed in URL parameters. Use the Authorization header instead."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The messages could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "sendMessage",
        "summary": "Send a message",
        "description": "Sends one SMS or MMS, or with `channel` a WhatsApp or RCS message. A test key, or a sandbox number such as `+15005550000`, simulates the send: nothing reaches a handset and nothing is charged. A live key on an account that cannot send to the destination yet is simulated too, and says so in `simulated` and `simulatedReason`.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "send"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The message to send.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessageRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- SMS or MMS sent: An SMS or MMS was accepted, or simulated. A live send the carrier refused at once answers this too, still `queued` with its quoted `creditsUsed`, while the message is already failed and refunded (or `retrying`, when it is retried).\n- WhatsApp message sent: WhatsApp accepted the message, or, with `fallbackToSms`, couldn't take it and the text went as an SMS (`status: \"failed\"`, `fallback.status: \"sent\"`).\n- WhatsApp message sent, partly recorded: WhatsApp accepted the message, then recording it failed.\n- RCS message sent: The recipient can receive RCS and the message was accepted.\n- RCS requested, sent as SMS: The recipient cannot receive RCS, so the text went as an SMS.\n- Short code message sent: The message was sent from the workspace's short code.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SmsSendResult"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSendResult"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSendRecoveredResult"
                    },
                    {
                      "$ref": "#/components/schemas/RcsSendResult"
                    },
                    {
                      "$ref": "#/components/schemas/RcsSmsFallbackResult"
                    },
                    {
                      "$ref": "#/components/schemas/ShortCodeSendResult"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key's SMS, simulated as delivered.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "to": "+15555550100",
                      "from": "SENDLY-TEST",
                      "text": "Your Sendly code is 123456",
                      "status": "delivered",
                      "direction": "outbound",
                      "error": null,
                      "segments": 1,
                      "creditsUsed": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "metadata": {
                        "orderId": "A-100"
                      },
                      "simulated": true
                    }
                  },
                  "sandbox-failure": {
                    "summary": "A test key's SMS to the sandbox number +15005550001, simulated as failed.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000003",
                      "to": "+15005550001",
                      "from": "SENDLY-TEST",
                      "text": "Your Sendly code is 123456",
                      "status": "failed",
                      "direction": "outbound",
                      "error": "Invalid phone number",
                      "segments": 1,
                      "creditsUsed": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "metadata": {},
                      "simulated": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `channel_not_supported`: `channel` is not `sms`, `whatsapp` or `rcs`.\n- `invalid_request`: A field is missing or malformed: `to`, `text` (or `from` for WhatsApp), the phone number format, `messageType`, `metadata`, the media URLs, or media to a destination outside the US and Canada.\n- `compliance_blocked`: The text has restricted (SHAFT) content. For WhatsApp, this checks the text, the media caption, or the template body with its variables filled in.\n- `contact_opted_out`: The recipient opted out.\n- `compliance_blocked`: A marketing message during the recipient's quiet hours.\n- `compliance_blocked`: A short code marketing message, or an RCS message that would fall back to SMS, during the recipient's quiet hours. An RCS send checks quiet hours once, before the capability check, so the RCS leg and its fallback answer alike.\n- `TRANSACTIONAL_MARKETING_MISMATCH`: A message marked transactional reads as marketing during quiet hours, on the SMS path or an RCS send.\n- `unsupported_destination`: The destination country is not supported, or a short code was asked to send outside the US.\n- `invalid_from_number`: `from` is not an active number of this workspace that can send here.\n- `whatsapp_invalid_content`: The WhatsApp content is invalid: not exactly one of text, media or template, too long, or the wrong template variables.\n- `rcs_invalid_content`: The RCS content is invalid.\n- `rcs_agent_ambiguous`: The workspace has more than one RCS agent and `agentId` is missing.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "channel_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "channel_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "channel_not_supported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SHAFT_CONTENT_DETECTED"
                          ]
                        },
                        "category": {
                          "type": "string",
                          "description": "The restricted category the text matched. Known values: `sex`, `hate`, `alcohol`, `firearms`, `tobacco`, `cannabis`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "sex",
                            "hate",
                            "alcohol",
                            "firearms",
                            "tobacco",
                            "cannabis"
                          ]
                        },
                        "matchedTerms": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "category",
                        "matchedTerms",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: SHAFT content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "contact_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "contact_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "contact_opted_out"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "QUIET_HOURS_VIOLATION"
                          ]
                        },
                        "recipientTimezone": {
                          "type": "string"
                        },
                        "recipientLocalTime": {
                          "type": "string"
                        },
                        "quietHoursStart": {
                          "type": "string"
                        },
                        "quietHoursEnd": {
                          "type": "string"
                        },
                        "nextAllowedTime": {
                          "type": "string",
                          "format": "date-time",
                          "description": "The earliest time a marketing message may go. ISO 8601, in UTC."
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "recipientTimezone",
                        "recipientLocalTime",
                        "quietHoursStart",
                        "quietHoursEnd",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: quiet hours",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "QUIET_HOURS_VIOLATION"
                          ]
                        },
                        "recipientTimezone": {
                          "type": "string"
                        },
                        "nextAllowedTime": {
                          "type": "string",
                          "format": "date-time",
                          "description": "The earliest time a marketing message may go. ISO 8601, in UTC."
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "recipientTimezone",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: quiet hours, short code",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "TRANSACTIONAL_MARKETING_MISMATCH"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "matchedKeywords": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "suggestion": {
                          "type": "string"
                        },
                        "reason": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "transactional_marketing_mismatch"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "matchedKeywords",
                        "suggestion",
                        "reason"
                      ],
                      "description": "Has no `error` field: the code is in `code`.",
                      "title": "TRANSACTIONAL_MARKETING_MISMATCH",
                      "x-sendly-error-shape": "codeless",
                      "x-sendly-error-codes": [
                        "TRANSACTIONAL_MARKETING_MISMATCH"
                      ],
                      "x-sendly-proposed-codes": [
                        "transactional_marketing_mismatch"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "unsupported_destination"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "country": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The destination's country code, when known."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "country"
                      ],
                      "title": "unsupported_destination",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "unsupported_destination"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_from_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "INVALID_FROM_NUMBER"
                          ],
                          "description": "Present when the account could not send here at all; absent when the number is not usable for a US or Canada destination."
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_from_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_from_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_invalid_content"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_invalid_content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_invalid_content"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_invalid_content"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_invalid_content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_invalid_content"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_agent_ambiguous"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_agent_ambiguous",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_agent_ambiguous"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A body that is not valid JSON, answered by the body parser.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  },
                  "default": {
                    "summary": "The text is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Missing required fields: 'to' and 'text'"
                    }
                  },
                  "unknown-channel": {
                    "summary": "A channel the API does not have.",
                    "value": {
                      "error": "channel_not_supported",
                      "message": "Unknown channel 'fax'. Supported channels: sms (default), whatsapp, rcs."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  },
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: The balance does not cover the message.\n- `insufficient_credits`: Charging the message failed, for any reason: too few credits, no credit balance for the account, a failed balance update, a workspace credit pool that refused (such as `overage_cap_reached`, with `currentBalance` 0), or a database error. `message` is the charge's own error text, which can be an internal error message. The same on the SMS, WhatsApp, RCS and short code paths.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_credits"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "creditsNeeded": {
                          "type": "integer"
                        },
                        "currentBalance": {
                          "type": "integer"
                        },
                        "tier": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The destination's price tier. Known values: `domestic`, `tier1`, `tier2`, `tier3`, `tier4`, `tier5`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "domestic",
                            "tier1",
                            "tier2",
                            "tier3",
                            "tier4",
                            "tier5"
                          ]
                        },
                        "pricePerSms": {
                          "type": "number",
                          "description": "The price of one segment, in US dollars."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "creditsNeeded",
                        "currentBalance",
                        "tier",
                        "pricePerSms"
                      ],
                      "title": "insufficient_credits, with the price",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_credits"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientCreditsError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `whatsapp_not_enabled`: WhatsApp is not enabled for the account.\n- `whatsapp_requires_live_key`, `rcs_requires_live_key`: A test key sent a WhatsApp or RCS message, which are never simulated.\n- `feature_disabled`: MMS is not enabled for the account.\n- `ACCOUNT_UNDER_REVIEW`: A new account sent text that reads like a payment scam. A workspace key also suspends the workspace.\n- `destination_not_authorized`: The account's verification does not cover this destination, or, for WhatsApp, the destination country is turned off in the account's Allowed countries.\n- `sender_not_authorized`: The `from` number is not authorized for this destination yet.\n- `registration_required`: The destination country needs a registered sender ID first.\n- `short_code_suspended`, `short_code_not_ready`, `short_code_cancelled`: The short code is suspended, cancelled, or not live yet.\n- `short_code_requires_live_key`: A test key sent from the workspace's own short code, which is never simulated.\n- `short_codes_not_enabled`: `from` is one of the workspace's short codes and short codes are not enabled for the workspace.\n- `recipient_opted_out`: The recipient opted out (WhatsApp, RCS and short codes).\n- `recipient_opted_out`: The carrier refused a short code send because the recipient opted out. The opt-out is recorded and the message is failed and refunded.\n- `account_under_review`: A new account's WhatsApp send, or an RCS send that would fall back to SMS, has text that reads like a payment scam. A workspace key also suspends the workspace.\n- `whatsapp_sender_not_connected`: `from` is not connected to WhatsApp on this workspace.\n- `rcs_agent_not_ready`: The RCS agent is not approved, suspended, or not fully set up.\n- `sms_fallback_unavailable`: The recipient cannot receive RCS, or a WhatsApp send asked for `fallbackToSms`, and the account cannot send SMS from that number to that recipient.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_not_enabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_not_enabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_not_enabled"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_requires_live_key",
                            "rcs_requires_live_key"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_requires_live_key, rcs_requires_live_key",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_requires_live_key",
                        "rcs_requires_live_key"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Your account has been flagged for review. Please contact support."
                          ]
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "ACCOUNT_UNDER_REVIEW"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "account_under_review"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error",
                        "code"
                      ],
                      "description": "`error` holds a sentence; the code is in `code`.",
                      "title": "ACCOUNT_UNDER_REVIEW",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [
                        "ACCOUNT_UNDER_REVIEW"
                      ],
                      "x-sendly-proposed-codes": [
                        "account_under_review"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "destination_not_authorized"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "DESTINATION_NOT_AUTHORIZED"
                          ]
                        },
                        "destinationCountry": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "destination_not_authorized",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "destination_not_authorized"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "sender_not_authorized"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SENDER_NOT_AUTHORIZED"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "sender_not_authorized",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "sender_not_authorized"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "registration_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SENDER_ID_NOT_REGISTERED"
                          ]
                        },
                        "countryCode": {
                          "type": "string"
                        },
                        "countryName": {
                          "type": "string"
                        },
                        "registrationUrl": {
                          "type": "string",
                          "description": "A dashboard path that starts the registration request."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "countryCode",
                        "countryName",
                        "registrationUrl"
                      ],
                      "title": "registration_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "registration_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_suspended",
                            "short_code_not_ready",
                            "short_code_cancelled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "short_code_suspended, short_code_not_ready, short_code_cancelled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_suspended",
                        "short_code_not_ready",
                        "short_code_cancelled"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_requires_live_key"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "short_code_requires_live_key",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_requires_live_key"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_codes_not_enabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "short_codes_not_enabled: a short code send",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_codes_not_enabled"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "recipient_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "recipient_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "recipient_opted_out"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "recipient_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "id": {
                          "type": "string",
                          "description": "The failed message's id."
                        },
                        "errorCode": {
                          "type": "string",
                          "description": "The error code, such as `E001`."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "id",
                        "errorCode"
                      ],
                      "title": "recipient_opted_out: the carrier refused a short code send",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "recipient_opted_out"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "account_under_review"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "ACCOUNT_UNDER_REVIEW"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "account_under_review: an RCS send's SMS fallback",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "account_under_review"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_sender_not_connected"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_sender_not_connected",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_sender_not_connected"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_agent_not_ready"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "agentStatus": {
                          "type": "string",
                          "description": "The agent's registration status."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "agentStatus"
                      ],
                      "title": "rcs_agent_not_ready",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_agent_not_ready"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "sms_fallback_unavailable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "suggestion"
                      ],
                      "title": "sms_fallback_unavailable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "sms_fallback_unavailable"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "whatsapp-test-key": {
                    "summary": "A test key asked for a WhatsApp send, which is never simulated.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp messages require a live API key. Test keys cannot simulate WhatsApp delivery."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled or not set up for the account, or `agentId` is unknown.\n- `whatsapp_template_not_found`: No template with that name and language exists for the sender.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_enabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_not_enabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_enabled"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_template_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "suggestion"
                      ],
                      "title": "whatsapp_template_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_template_not_found"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `whatsapp_send_unconfirmed`: WhatsApp may have accepted the message. It is marked failed and refunded, but can still arrive: check before sending again.\n- `rcs_send_unconfirmed`, `short_code_send_unconfirmed`: The RCS network or the short code carrier may have accepted the message. It is marked failed and refunded, but can still arrive: check before sending again. These sends are not retried when the outcome is unknown.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_send_unconfirmed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errorCode": {
                          "type": "string",
                          "description": "The error code, such as `E001`."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errorCode"
                      ],
                      "title": "whatsapp_send_unconfirmed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_send_unconfirmed"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_send_unconfirmed",
                            "short_code_send_unconfirmed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errorCode": {
                          "type": "string",
                          "description": "The error code, such as `E001`."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errorCode"
                      ],
                      "title": "Channel send unconfirmed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_send_unconfirmed",
                        "short_code_send_unconfirmed"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `undeliverable_number`: The recipient is flagged as unable to receive texts.\n- `no_sending_number`: `to` is in the US or Canada, `from` is missing, and the workspace's toll-free number was released with no other active number that can text there. Nothing was sent or charged.\n- `whatsapp_template_not_approved`: The template is not approved.\n- `whatsapp_window_closed`: The 24-hour window is closed, so only a template can go. With `fallbackToSms`, the SMS couldn't go either: `fallback` says why.\n- `sms_fallback_not_supported`: `fallbackToSms` on a marketing or authentication template, or on media without a caption.\n- `whatsapp_send_failed`: WhatsApp refused the message. Nothing was sent and the charge was refunded.\n- `rcs_not_supported_for_recipient`: The recipient cannot receive RCS, and `fallbackToSms` is `false` or the message is a card.\n- `rcs_destination_not_supported`: RCS reaches US numbers only. The recipient is outside the US, and `fallbackToSms` is `false` or the message is a card.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "undeliverable_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "description": "Why the number cannot receive texts. Known values: `undeliverable_landline`, `undeliverable_invalid`, `undeliverable_non_sms`, `undeliverable_number`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "undeliverable_landline",
                            "undeliverable_invalid",
                            "undeliverable_non_sms",
                            "undeliverable_number"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "undeliverable_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "undeliverable_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_sending_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "no_sending_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_sending_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_template_not_approved"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "templateStatus": {
                          "type": "string",
                          "description": "The template's review status, lower case."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "templateStatus"
                      ],
                      "title": "whatsapp_template_not_approved",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_template_not_approved"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_window_closed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        },
                        "windowExpiredAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the last window closed. ISO 8601, in UTC."
                        },
                        "id": {
                          "type": "string",
                          "description": "With `fallbackToSms`, the failed WhatsApp message's id."
                        },
                        "fallback": {
                          "type": "object",
                          "properties": {
                            "channel": {
                              "type": "string",
                              "enum": [
                                "sms"
                              ]
                            },
                            "status": {
                              "type": "string",
                              "description": "`pending` until WhatsApp's outcome is known; `sent` when the SMS went; `failed` when the SMS carrier refused it or credits ran out; `unavailable` when the SMS could no longer be sent from this number; `skipped` when the WhatsApp failure isn't one an SMS fixes, such as the recipient opting out. Known values: `pending`, `sent`, `failed`, `unavailable`, `skipped`. More can be added at any time, so treat an unknown value as valid.",
                              "x-sendly-extensible-enum": [
                                "pending",
                                "sent",
                                "failed",
                                "unavailable",
                                "skipped"
                              ]
                            },
                            "reason": {
                              "type": "string",
                              "description": "What made the message fall back. Known values: `window_closed`, `whatsapp_refused`, `whatsapp_failed`. More can be added at any time, so treat an unknown value as valid.",
                              "x-sendly-extensible-enum": [
                                "window_closed",
                                "whatsapp_refused",
                                "whatsapp_failed"
                              ]
                            },
                            "messageId": {
                              "type": "string",
                              "description": "The SMS message's id, once it exists."
                            },
                            "creditsUsed": {
                              "type": "integer",
                              "description": "Credits charged for the SMS."
                            },
                            "error": {
                              "type": "string",
                              "description": "Why the SMS didn't go, in plain English."
                            },
                            "contentDropped": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Template parts with no SMS form, such as `quick_replies` or `header_media`."
                            }
                          },
                          "required": [
                            "channel",
                            "status"
                          ],
                          "description": "The SMS fallback of a WhatsApp message sent with `fallbackToSms: true`."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "suggestion"
                      ],
                      "title": "whatsapp_window_closed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_window_closed"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "sms_fallback_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "reason": {
                          "type": "string",
                          "description": "Why this message can't fall back to SMS. Known values: `marketing_template`, `authentication_template`, `media_without_caption`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "marketing_template",
                            "authentication_template",
                            "media_without_caption"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "reason"
                      ],
                      "title": "sms_fallback_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "sms_fallback_not_supported"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_send_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errorCode": {
                          "type": "string",
                          "description": "The error code, such as `E001`."
                        },
                        "fallback": {
                          "type": "object",
                          "properties": {
                            "channel": {
                              "type": "string",
                              "enum": [
                                "sms"
                              ]
                            },
                            "status": {
                              "type": "string",
                              "description": "`pending` until WhatsApp's outcome is known; `sent` when the SMS went; `failed` when the SMS carrier refused it or credits ran out; `unavailable` when the SMS could no longer be sent from this number; `skipped` when the WhatsApp failure isn't one an SMS fixes, such as the recipient opting out. Known values: `pending`, `sent`, `failed`, `unavailable`, `skipped`. More can be added at any time, so treat an unknown value as valid.",
                              "x-sendly-extensible-enum": [
                                "pending",
                                "sent",
                                "failed",
                                "unavailable",
                                "skipped"
                              ]
                            },
                            "reason": {
                              "type": "string",
                              "description": "What made the message fall back. Known values: `window_closed`, `whatsapp_refused`, `whatsapp_failed`. More can be added at any time, so treat an unknown value as valid.",
                              "x-sendly-extensible-enum": [
                                "window_closed",
                                "whatsapp_refused",
                                "whatsapp_failed"
                              ]
                            },
                            "messageId": {
                              "type": "string",
                              "description": "The SMS message's id, once it exists."
                            },
                            "creditsUsed": {
                              "type": "integer",
                              "description": "Credits charged for the SMS."
                            },
                            "error": {
                              "type": "string",
                              "description": "Why the SMS didn't go, in plain English."
                            },
                            "contentDropped": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Template parts with no SMS form, such as `quick_replies` or `header_media`."
                            }
                          },
                          "required": [
                            "channel",
                            "status"
                          ],
                          "description": "The SMS fallback of a WhatsApp message sent with `fallbackToSms: true`."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errorCode"
                      ],
                      "title": "whatsapp_send_failed: refused",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_send_failed"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_supported_for_recipient"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "suggestion"
                      ],
                      "title": "rcs_not_supported_for_recipient",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_supported_for_recipient"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_destination_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "suggestion"
                      ],
                      "title": "rcs_destination_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_destination_not_supported"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The first send's Idempotency-Key, reused with a different body.",
                    "value": {
                      "error": "idempotency_key_mismatch",
                      "message": "This idempotency key was already used with a different request body. Use a new key for different requests."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The send failed unexpectedly. A failed WhatsApp, RCS or short code send is refunded.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_send_failed`, `rcs_send_failed`, `sms_fallback_failed`: The carrier network did not take the message. Nothing was sent and the charge was refunded.\n- `short_code_send_failed`: The short code carrier did not take the message. It is recorded as failed and refunded.\n- `rcs_capability_check_failed`: Whether the recipient has RCS could not be checked. Nothing was sent.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_send_failed",
                            "rcs_send_failed",
                            "sms_fallback_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errorCode": {
                          "type": "string",
                          "description": "The error code, such as `E001`."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errorCode"
                      ],
                      "title": "Channel send failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_send_failed",
                        "rcs_send_failed",
                        "sms_fallback_failed"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_send_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "id": {
                          "type": "string",
                          "description": "The failed message's id."
                        },
                        "errorCode": {
                          "type": "string",
                          "description": "The error code, such as `E001`."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "id",
                        "errorCode"
                      ],
                      "title": "short_code_send_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_send_failed"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_capability_check_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "suggestion"
                      ],
                      "title": "rcs_capability_check_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_capability_check_failed"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/batch": {
      "post": {
        "operationId": "sendMessageBatch",
        "summary": "Send a batch",
        "description": "Sends one SMS or MMS to each of up to 10,000 recipients and charges for all of them up front. A live key's batch is sent in the background and answers 202. A test key's batch is simulated: it answers 202 too when the `batch_idempotency_v2` flag is on for the account, and otherwise is sent before the answer, which is then 201. Quiet hours do not hold back a marketing batch. Without an Idempotency-Key, the same recipients, texts, `messageType` and `mediaUrls` sent again within 24 hours get the first answer back, whatever the `from` and `metadata`, a 400, 402 or 403 included.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "sendBatch"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The recipients and the message.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessageBatchRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- Batch sent: A test key's batch was simulated before the answer: the `batch_idempotency_v2` flag is off for the account, or handing the batch to the background failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageBatchCompleted"
                },
                "examples": {
                  "default": {
                    "summary": "A test key's batch sent before the answer, one message to the failure sandbox number +15005550001: built from sendBatch's in-process path, which production takes for a test key only when the batch_idempotency_v2 flag is off, as it is not for the capture account.",
                    "value": {
                      "batchId": "batch_placeholder1",
                      "status": "partial_failure",
                      "total": 2,
                      "sent": 1,
                      "failed": 1,
                      "retrying": 0,
                      "optedOutSkipped": 0,
                      "invalidSkipped": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "messages": [
                        {
                          "index": 0,
                          "id": "msg_placeholder2",
                          "to": "+15555550100",
                          "status": "sent"
                        },
                        {
                          "index": 1,
                          "id": "msg_placeholder3",
                          "to": "+15005550001",
                          "status": "failed",
                          "error": "Invalid phone number"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted.\n\n- Batch accepted: The batch is being sent in the background. A test key's batch sent this way is simulated as sent for every recipient, failure sandbox numbers included.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageBatchAccepted"
                },
                "examples": {
                  "default": {
                    "summary": "A test key's batch of two, one of them to the sandbox number +15005550001, accepted and sent in the background.",
                    "value": {
                      "batchId": "batch_placeholder1",
                      "status": "processing",
                      "total": 2,
                      "sent": 0,
                      "failed": 0,
                      "optedOutSkipped": 0,
                      "invalidSkipped": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "messages": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `channel_not_supported`: `channel`, or a recipient's `channel`, is anything but `sms`.\n- `invalid_request`: `messages` is missing, not an array or empty, a recipient is not an object, has no `to`, a `to` that is not a string or not a phone number, a `text` that is not a string, or no text, the shared `text` is not a string, `messageType` is not one of the two, a media URL was not uploaded through `POST /api/v1/media` or there are more than 10, or media goes outside the US and Canada.\n- `invalid_from_number`: `from` is not a number of this workspace that can send.\n- `mms_unsupported_sender`: Media sent from a toll-free `from` number.\n- `batch_too_large`: More than 10,000 recipients.\n- `all_opted_out`: Every recipient opted out.\n- `all_recipients_blocked`: Every recipient opted out or has a number flagged as unable to receive texts, and at least one is flagged.\n- `compliance_blocked`: A text has restricted (SHAFT) content.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "channel_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "channel_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "channel_not_supported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_from_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "INVALID_FROM_NUMBER"
                          ],
                          "description": "Present when the account could not send here at all; absent when the number is not usable for a US or Canada destination."
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_from_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_from_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "mms_unsupported_sender"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "mms_unsupported_sender",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "mms_unsupported_sender"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "batch_too_large"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "batch_too_large",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "batch_too_large"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "all_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "optedOutCount": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "optedOutCount"
                      ],
                      "title": "all_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "all_opted_out"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "all_recipients_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "optedOutCount": {
                          "type": "integer"
                        },
                        "invalidCount": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "optedOutCount",
                        "invalidCount"
                      ],
                      "title": "all_recipients_blocked",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "all_recipients_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SHAFT_CONTENT_DETECTED"
                          ]
                        },
                        "category": {
                          "type": "string",
                          "description": "The restricted category the text matched. Known values: `sex`, `hate`, `alcohol`, `firearms`, `tobacco`, `cannabis`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "sex",
                            "hate",
                            "alcohol",
                            "firearms",
                            "tobacco",
                            "cannabis"
                          ]
                        },
                        "matchedTerms": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "category",
                        "matchedTerms",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: SHAFT content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "`messages` is empty.",
                    "value": {
                      "error": "invalid_request",
                      "message": "messages array is required and must not be empty"
                    }
                  },
                  "missing-text": {
                    "summary": "A recipient without text, and no shared text.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Message at index 0 is missing 'text' field and no shared text provided"
                    }
                  },
                  "unknown-channel": {
                    "summary": "A recipient on a channel the endpoint does not take.",
                    "value": {
                      "error": "channel_not_supported",
                      "message": "RCS is not supported on this endpoint. Send RCS messages one at a time via POST /v1/messages with channel \"rcs\"."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: A live key's balance does not cover the batch.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "insufficient_credits"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "creditsNeeded": {
                      "type": "integer"
                    },
                    "currentBalance": {
                      "type": "integer"
                    },
                    "messageCount": {
                      "type": "integer",
                      "description": "How many recipients the send had."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "creditsNeeded",
                    "currentBalance",
                    "messageCount"
                  ],
                  "title": "insufficient_credits, for a batch",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "insufficient_credits"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `feature_disabled`: MMS is not enabled for the account.\n- `workspace_suspended`: The key's workspace is suspended.\n- `account_under_review`: A live key on an account less than 48 hours old sent text that reads like a payment scam. A workspace key also suspends the workspace.\n- `not_verified`: A live key on an account with no verified sending setup yet.\n- `access_denied`: A live key's verification does not cover a recipient's destination.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "account_under_review"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "account_under_review",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "account_under_review"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "not_verified"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "not_verified",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "not_verified"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "access_denied"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "access_denied",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "access_denied"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `no_sending_number`: A live key's batch has a US or Canadian recipient, and the workspace's toll-free number was released with no other active number that can text there. Nothing was sent or charged.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_sending_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "no_sending_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_sending_number"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The first batch's Idempotency-Key, reused with a different body.",
                    "value": {
                      "error": "idempotency_key_mismatch",
                      "message": "This idempotency key was already used with a different request body. Use a new key for different requests."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `quota_exceeded`: The batch would take the workspace past its monthly quota.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "quota_exceeded"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "quota": {
                          "type": "integer",
                          "description": "The workspace's monthly message quota."
                        },
                        "used": {
                          "type": "integer",
                          "description": "Messages sent this month."
                        },
                        "batchSize": {
                          "type": "integer",
                          "description": "How many messages the send would add."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "quota",
                        "used",
                        "batchSize"
                      ],
                      "title": "quota_exceeded, for a batch",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "quota_exceeded"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/batch/preview": {
      "post": {
        "operationId": "previewMessageBatch",
        "summary": "Preview a batch",
        "description": "Checks a batch without sending it: what it would cost, which recipients are blocked and why, and compliance warnings. Nothing is sent or charged.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "previewBatch"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The batch to check.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreviewMessageBatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- MessageBatchPreview: The preview.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageBatchPreview"
                },
                "examples": {
                  "default": {
                    "summary": "A test key's preview of three recipients, one of them repeated, one a failure sandbox number.",
                    "value": {
                      "total": 3,
                      "sendable": 2,
                      "blocked": 0,
                      "duplicates": 1,
                      "creditsNeeded": 4,
                      "creditBalance": 170,
                      "hasSufficientCredits": true,
                      "pooled": false,
                      "keyType": "test",
                      "keyScopes": [
                        "sms:send",
                        "sms:read"
                      ],
                      "hasWriteScope": true,
                      "messagingProfile": {
                        "id": "00000000-0000-4000-8000-000000000003",
                        "canSendDomestic": true,
                        "canSendInternational": true,
                        "verificationStatus": "verified",
                        "verificationType": "both"
                      },
                      "byCountry": {
                        "US": {
                          "count": 2,
                          "credits": 4,
                          "tier": "domestic",
                          "allowed": true
                        }
                      },
                      "blockedMessages": [],
                      "compliance": {
                        "messageType": "marketing",
                        "optedOutBlocked": 0,
                        "shaftBlocked": 0,
                        "quietHoursBlocked": 0,
                        "quietHoursRescheduled": 0,
                        "shaftBlockedMessages": [],
                        "quietHoursBlockedMessages": []
                      },
                      "warnings": [
                        "1 duplicate number will be removed",
                        "Using TEST key - messages will be simulated in sandbox mode",
                        "Marketing messages are subject to quiet hours enforcement (8pm-8am recipient local time)"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `channel_not_supported`: `channel`, or a recipient's `channel`, is anything but `sms`.\n- `invalid_request`: `messages` is missing, not an array or empty, a recipient is not an object or has no `to` string, a `text` or the shared `text` is not a string, or `messageType` is not one of the two. A `to` that is not a phone number is listed as blocked instead.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "channel_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "channel_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "channel_not_supported"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "`messages` is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "messages array is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/batch/{id}": {
      "get": {
        "operationId": "getMessageBatch",
        "summary": "Get a batch",
        "description": "Returns one batch with its counts and every message it sent, without deleted messages. A test key reads only a batch with no live messages and no credits reserved.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "getBatch"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The batch's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- MessageBatch: The batch.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageBatch"
                },
                "examples": {
                  "default": {
                    "summary": "The test key's simulated batch.",
                    "value": {
                      "id": "batch_placeholder1",
                      "status": "completed",
                      "total": 2,
                      "queued": 2,
                      "sent": 2,
                      "delivered": 0,
                      "failed": 0,
                      "creditsReserved": 0,
                      "creditsUsed": 0,
                      "creditsRefunded": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "completedAt": "2026-01-01T00:00:00.000Z",
                      "messages": [
                        {
                          "id": "msg_placeholder2",
                          "to": "+15555550100",
                          "status": "sent",
                          "error": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "deliveredAt": null
                        },
                        {
                          "id": "msg_placeholder3",
                          "to": "+15005550001",
                          "status": "sent",
                          "error": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "deliveredAt": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No batch with this id belongs to the key's workspace (for a key with no workspace, to its user, outside any workspace), or a test key asked for a batch with live messages or reserved credits.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no batch.",
                    "value": {
                      "error": "not_found",
                      "message": "Batch not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/batches": {
      "get": {
        "operationId": "listMessageBatches",
        "summary": "List batches",
        "description": "Lists the workspace's batches, newest first. A test key lists only simulated batches.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "count",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "listBatches"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size, 1 to 100. Defaults to 50, which is also what 0 or a value that is not a number gives. A value below 1 is raised to 1, and one above 100 is lowered to 100."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many to skip. Ignored when `page` is set."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "The page to return, starting at 1. Takes precedence over `offset`."
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only batches with this status, as the list shows it."
            },
            "required": false,
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- MessageBatchList: A page of batches.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageBatchList"
                },
                "examples": {
                  "default": {
                    "summary": "The two newest batches.",
                    "value": {
                      "data": [
                        {
                          "id": "batch_placeholder1",
                          "status": "completed",
                          "total": 2,
                          "queued": 2,
                          "sent": 2,
                          "delivered": 0,
                          "failed": 0,
                          "creditsReserved": 0,
                          "creditsUsed": 0,
                          "creditsRefunded": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "completedAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "batch_placeholder4",
                          "status": "completed",
                          "total": 2,
                          "queued": 2,
                          "sent": 2,
                          "delivered": 0,
                          "failed": 0,
                          "creditsReserved": 0,
                          "creditsUsed": 0,
                          "creditsRefunded": 0,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "completedAt": "2026-01-01T00:00:00.000Z"
                        }
                      ],
                      "count": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The batches could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/group": {
      "post": {
        "operationId": "sendGroupMessage",
        "summary": "Send a group message",
        "description": "Sends one group MMS to 2 to 8 US or Canada recipients, billed per recipient at the MMS rate. A test key, or an account not verified for the US and Canada yet, is simulated. Behind the `group_mms` flag.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "sendGroup"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The recipients and the message.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendGroupMessageRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- Group message simulated: The group message was simulated.\n- Group message sent: The carrier took the group message.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/GroupMessageSimulated"
                    },
                    {
                      "$ref": "#/components/schemas/GroupMessageSent"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key's group message to two recipients, simulated.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "status": "delivered",
                      "to": [
                        "+15555550100",
                        "+15555550101"
                      ],
                      "simulated": true,
                      "message": "Group message simulated (test key or verification pending)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `channel_not_supported`: `channel` is set to anything but `sms`.\n- `invalid_request`: `to` is not an array of 2 to 8 recipients, or of 2 distinct ones, there is neither text nor media, or a media URL was not uploaded through `POST /api/v1/media`.\n- `invalid_phone`: A recipient is not a valid phone number.\n- `unsupported_destination`: A recipient is outside the US and Canada.\n- `compliance_blocked`: The text has restricted (SHAFT) content.\n- `sandbox_number_in_live_mode`: A live key sent to a sandbox number.\n- `contact_opted_out`: A live key sent to a recipient who opted out.\n- `compliance_blocked`: A live key's marketing group message during a recipient's quiet hours.\n- `compliance_blocked`: A live key's transactional group message reads as marketing during a recipient's quiet hours.\n- `invalid_from_number`: `from` is not a number of this workspace that can send.\n- `no_group_sender`: The workspace has no number to send a group message from.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "channel_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "channel_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "channel_not_supported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_phone"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_phone",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_phone"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "unsupported_destination"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "unsupported_destination: group",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "unsupported_destination"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SHAFT_CONTENT_DETECTED"
                          ]
                        },
                        "category": {
                          "type": "string",
                          "description": "The restricted category the text matched. Known values: `sex`, `hate`, `alcohol`, `firearms`, `tobacco`, `cannabis`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "sex",
                            "hate",
                            "alcohol",
                            "firearms",
                            "tobacco",
                            "cannabis"
                          ]
                        },
                        "matchedTerms": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "category",
                        "matchedTerms"
                      ],
                      "title": "compliance_blocked: SHAFT content, group",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "sandbox_number_in_live_mode"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "sandbox_number_in_live_mode",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "sandbox_number_in_live_mode"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "contact_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "contact_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "contact_opted_out"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "QUIET_HOURS_VIOLATION"
                          ]
                        },
                        "recipient": {
                          "type": "string"
                        },
                        "nextAllowedTime": {
                          "type": "string",
                          "format": "date-time",
                          "description": "The earliest time a marketing message may go. ISO 8601, in UTC."
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "recipient",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: quiet hours, group",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "TRANSACTIONAL_MARKETING_MISMATCH"
                          ]
                        },
                        "matchedKeywords": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "recipient": {
                          "type": "string"
                        },
                        "reason": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "matchedKeywords",
                        "recipient",
                        "reason"
                      ],
                      "title": "compliance_blocked: transactional text reads as marketing, group",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_from_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "INVALID_FROM_NUMBER"
                          ],
                          "description": "Present when the account could not send here at all; absent when the number is not usable for a US or Canada destination."
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_from_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_from_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_group_sender"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "NO_GROUP_SENDER"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "no_group_sender",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_group_sender"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "invalid-phone": {
                    "summary": "A recipient that is not a valid phone number.",
                    "value": {
                      "error": "invalid_phone",
                      "message": "Invalid recipient: +15555550142. Use E.164 (e.g. +15555550102)"
                    }
                  },
                  "default": {
                    "summary": "Only one recipient.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Group messaging needs at least 2 recipients in 'to'"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: The balance does not cover every recipient.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InsufficientCreditsError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `feature_disabled`: Group messaging, or MMS for a message with media, is not enabled.\n- `sender_not_authorized`: A live key sent `from` a number on an account not verified for the US and Canada yet.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "sender_not_authorized"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SENDER_NOT_AUTHORIZED"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "sender_not_authorized",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "sender_not_authorized"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `undeliverable_number`: A live key sent to a recipient flagged as unable to receive texts.\n- `send_failed`: The carrier refused the group message. It is failed and refunded, and `message` is the carrier's own error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "undeliverable_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "description": "Why the number cannot receive texts. Known values: `undeliverable_landline`, `undeliverable_invalid`, `undeliverable_non_sms`, `undeliverable_number`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "undeliverable_landline",
                            "undeliverable_invalid",
                            "undeliverable_non_sms",
                            "undeliverable_number"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code"
                      ],
                      "title": "undeliverable_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "undeliverable_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "send_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "send_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "send_failed"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Messaging not configured: No messaging profile is available to send from.\n- `server_error`: The send failed unexpectedly. `message` is the exception's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "Messaging not configured"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "configuration_error"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Messaging not configured",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "configuration_error"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/schedule": {
      "post": {
        "operationId": "scheduleMessage",
        "summary": "Schedule a message",
        "description": "Schedules one SMS or MMS for 5 minutes to 5 days from now, and charges its credits at once. Quiet hours do not move or refuse a marketing message here. It needs a live key: a scheduled message is delivered for real, so a test key or a CLI session is refused.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "schedule"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The message and when to send it.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleMessageRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- ScheduledMessageCreated: The message is scheduled and its credits are charged.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledMessageCreated"
                },
                "examples": {
                  "default": {
                    "summary": "A message scheduled for a US recipient: built from scheduleMessage, since scheduling with any key charges credits and schedules a real send.",
                    "value": {
                      "id": "schd_placeholder1",
                      "to": "+15555550100",
                      "text": "Your Sendly code is 123456",
                      "scheduledAt": "2026-01-02T15:00:00.000Z",
                      "timezone": "America/New_York",
                      "status": "scheduled",
                      "creditsReserved": 2,
                      "segments": 1,
                      "senderType": "number_pool",
                      "createdAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `channel_not_supported`: `channel` is set to anything but `sms`.\n- `invalid_request`: `to`, `scheduledAt`, or `text` without media is missing, `to` is not a string or not a phone number, `text` is not a string, `messageType` is not one of the two, a media URL was not uploaded through `POST /api/v1/media` or there are more than 10, or media goes outside the US and Canada.\n- `invalid_from_number`: `from` is not a number of this workspace that can send.\n- `mms_unsupported_sender`: Media sent from a toll-free `from` number.\n- `invalid_scheduled_time`: `scheduledAt` is not a timestamp, is less than 5 minutes away, or is more than 5 days away.\n- `contact_opted_out`: The recipient opted out.\n- `compliance_blocked`: The text has restricted (SHAFT) content.\n- `compliance_blocked`: A message marked transactional reads as marketing and would land in quiet hours.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "channel_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "channel_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "channel_not_supported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_from_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "INVALID_FROM_NUMBER"
                          ],
                          "description": "Present when the account could not send here at all; absent when the number is not usable for a US or Canada destination."
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_from_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_from_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "mms_unsupported_sender"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "mms_unsupported_sender",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "mms_unsupported_sender"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_scheduled_time"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_scheduled_time",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_scheduled_time"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "contact_opted_out"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "contact_opted_out",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "contact_opted_out"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SHAFT_CONTENT_DETECTED"
                          ]
                        },
                        "category": {
                          "type": "string",
                          "description": "The restricted category the text matched. Known values: `sex`, `hate`, `alcohol`, `firearms`, `tobacco`, `cannabis`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "sex",
                            "hate",
                            "alcohol",
                            "firearms",
                            "tobacco",
                            "cannabis"
                          ]
                        },
                        "matchedTerms": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "category",
                        "matchedTerms",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: SHAFT content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "TRANSACTIONAL_MARKETING_MISMATCH"
                          ]
                        },
                        "matchedKeywords": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "reason": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "matchedKeywords",
                        "reason",
                        "suggestion"
                      ],
                      "title": "compliance_blocked: transactional text reads as marketing",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-time": {
                    "summary": "`scheduledAt` is not a timestamp.",
                    "value": {
                      "error": "invalid_scheduled_time",
                      "message": "scheduledAt must be a valid ISO 8601 timestamp"
                    }
                  },
                  "default": {
                    "summary": "`scheduledAt` is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Missing required fields: 'to', 'text', and 'scheduledAt'"
                    }
                  },
                  "too-soon": {
                    "summary": "`scheduledAt` is in the past.",
                    "value": {
                      "error": "invalid_scheduled_time",
                      "message": "scheduledAt must be at least 5 minutes in the future"
                    }
                  },
                  "unknown-channel": {
                    "summary": "A channel the endpoint does not take.",
                    "value": {
                      "error": "channel_not_supported",
                      "message": "WhatsApp is not supported on this endpoint. Send WhatsApp messages one at a time via POST /v1/messages with channel \"whatsapp\"."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: The balance does not cover the message.\n- `insufficient_credits`: Charging the credits failed after the check, as when another send spent them first. The message is recorded as `failed` and nothing is scheduled.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/InsufficientCreditsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_credits"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "creditsNeeded": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "creditsNeeded"
                      ],
                      "title": "insufficient_credits, credits could not be reserved",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_credits"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `live_key_required`: A test key or a CLI session called it. Checked after `channel`, `messageType` and the media URLs.\n- `feature_disabled`: MMS is not enabled for the account.\n- `not_verified`: The account has no verified sending setup yet.\n- `access_denied`: The account's verification does not cover this destination, or the country needs a registered sender ID.\n- `workspace_suspended`: The key's workspace is suspended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "not_verified"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "not_verified",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "not_verified"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "access_denied"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "REGISTRATION_REQUIRED"
                          ],
                          "description": "Present when the country needs a registered sender ID first."
                        },
                        "countryCode": {
                          "type": "string"
                        },
                        "countryName": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "access_denied: scheduled message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "access_denied"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `undeliverable_landline`, `undeliverable_invalid`, `undeliverable_non_sms`, `undeliverable_number`: The recipient is flagged as unable to receive texts.\n- `no_sending_number`: `to` is in the US or Canada, and the workspace's toll-free number was released with no other active number that can text there. Nothing was scheduled or charged.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "undeliverable_landline",
                            "undeliverable_invalid",
                            "undeliverable_non_sms",
                            "undeliverable_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "The reason is the `error` code itself, with no separate `code`.",
                      "title": "Undeliverable number, scheduled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "undeliverable_landline",
                        "undeliverable_invalid",
                        "undeliverable_non_sms",
                        "undeliverable_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_sending_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "no_sending_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_sending_number"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An Idempotency-Key first used for a request refused with 400, reused with a different body.",
                    "value": {
                      "error": "idempotency_key_mismatch",
                      "message": "This idempotency key was already used with a different request body. Use a new key for different requests."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `quota_exceeded`: The workspace has used its monthly message quota.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "quota_exceeded"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "quota": {
                          "type": "integer"
                        },
                        "used": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "quota",
                        "used"
                      ],
                      "title": "quota_exceeded: one message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "quota_exceeded"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `scheduling_failed`: The carrier refused to schedule the message. The credits are refunded, and `message` is the carrier's own error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "scheduling_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "scheduling_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "scheduling_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/scheduled": {
      "get": {
        "operationId": "listScheduledMessages",
        "summary": "List scheduled messages",
        "description": "Lists the workspace's scheduled messages in every status, the soonest `scheduledAt` first.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "count",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "listScheduled"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size, 1 to 100. Defaults to 50, which is also what 0 or a value that is not a number gives. A value below 1 is raised to 1, and one above 100 is lowered to 100."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many to skip. Ignored when `page` is set."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "The page to return, starting at 1. Takes precedence over `offset`."
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only scheduled messages with exactly this status."
            },
            "required": false,
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ScheduledMessageList: A page of scheduled messages.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledMessageList"
                },
                "examples": {
                  "default": {
                    "summary": "The first five scheduled messages.",
                    "value": {
                      "data": [],
                      "count": 0
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The scheduled messages could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/scheduled/{id}": {
      "get": {
        "operationId": "getScheduledMessage",
        "summary": "Get a scheduled message",
        "description": "Returns one scheduled message, in any status.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "getScheduled"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The scheduled message's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- ScheduledMessage: The scheduled message.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledMessage"
                },
                "examples": {
                  "default": {
                    "summary": "A scheduled message that has not gone yet: built from getScheduledMessage, since the capture account has none and scheduling one charges credits.",
                    "value": {
                      "id": "schd_placeholder1",
                      "to": "+15555550100",
                      "text": "Your Sendly code is 123456",
                      "scheduledAt": "2026-01-02T15:00:00.000Z",
                      "timezone": "America/New_York",
                      "status": "scheduled",
                      "error": null,
                      "creditsReserved": 2,
                      "segments": 1,
                      "senderType": "number_pool",
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "cancelledAt": null,
                      "sentAt": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No scheduled message with this id was made by the key's user, or, for a workspace key, it is in another workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no scheduled message.",
                    "value": {
                      "error": "not_found",
                      "message": "Scheduled message not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "cancelScheduledMessage",
        "summary": "Cancel a scheduled message",
        "description": "Cancels a scheduled message that is more than a minute away and refunds its credits. For five minutes after it is created, while the carrier has not confirmed it, a cancel answers 409.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "cancelScheduled"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The scheduled message's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- CancelledScheduledMessage: The message is cancelled and its credits refunded.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelledScheduledMessage"
                },
                "examples": {
                  "default": {
                    "summary": "A scheduled message cancelled and refunded: built from cancelScheduledMessage, since cancelling a real one changes the carrier's schedule and the balance.",
                    "value": {
                      "id": "schd_placeholder1",
                      "status": "cancelled",
                      "creditsRefunded": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_status`: The message is no longer `scheduled`.\n- `too_late_to_cancel`: The message goes in less than a minute.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_status"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_status",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_status"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "too_late_to_cancel"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "too_late_to_cancel",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "too_late_to_cancel"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No scheduled message with this id was made by the key's user, or, for a workspace key, it is in another workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no scheduled message.",
                    "value": {
                      "error": "not_found",
                      "message": "Scheduled message not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `scheduling_in_progress`: The message is still being handed to the carrier: it has no carrier id yet and was created less than five minutes ago. Try again in a few seconds.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "scheduling_in_progress"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "scheduling_in_progress",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "scheduling_in_progress"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `cancel_failed`: The carrier did not cancel it. Nothing changed, and `message` is the carrier's own error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "cancel_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "cancel_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "cancel_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/{id}": {
      "get": {
        "operationId": "getMessage",
        "summary": "Get a message",
        "description": "Returns one message of this workspace, sent or received, live or simulated. A test key, or a CLI session, reads only simulated messages, and a deleted message is never returned.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "messages",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The message's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Message: The message.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "examples": {
                  "default": {
                    "summary": "The test key's simulated SMS.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000002",
                      "to": "+15555550100",
                      "from": "SENDLY-TEST",
                      "text": "Your Sendly code is 123456",
                      "status": "delivered",
                      "direction": "outbound",
                      "error": null,
                      "errorCode": null,
                      "retryCount": 0,
                      "segments": 1,
                      "creditsUsed": 0,
                      "isSandbox": true,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "deliveredAt": "2026-01-01T00:00:00.000Z",
                      "message_format": "sms",
                      "messageFormat": "sms"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No message with this id belongs to the key's workspace, the message was deleted, or it is a live message and a test key or CLI session asked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no message.",
                    "value": {
                      "error": "not_found",
                      "message": "Message not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The message could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/messages/{id}/labels": {
      "post": {
        "operationId": "addMessageLabels",
        "summary": "Label a message",
        "description": "Adds labels to a message. A label it already has is kept once. The message must be the key's own and not deleted (for a key with no workspace, one sent outside any workspace), and every label must belong to the key's workspace. Behind the `conversations_api` flag.",
        "tags": [
          "Messaging"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The message's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The labels to add.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddMessageLabelsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- MessageLabelsAdded: The labels are on the message.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageLabelsAdded"
                },
                "examples": {
                  "default": {
                    "summary": "A label made for the capture, added to the test key's simulated message. The label is deleted afterwards.",
                    "value": {
                      "success": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `labelIds` is missing, not an array or empty.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "`labelIds` is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "labelIds array is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The Conversations API is not enabled for the account.\n- `not_found`: No message with this id is the key's own, the message was deleted (`Message not found`), or a label id names no label of the key's workspace (`Label not found`). Nothing is attached.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/NotFoundError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/numbers": {
      "get": {
        "operationId": "listNumbers",
        "summary": "List numbers",
        "description": "Lists every number the key's workspace owns, newest first, in one response. Released numbers are left out. Behind the `number_porting` flag: while it is off for the account, every numbers operation answers 404 `not_found`.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "numbers:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "numbers",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- PhoneNumberList: The workspace's numbers. Can be empty.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneNumberList"
                },
                "examples": {
                  "default": {
                    "summary": "Two numbers, as the handler's projection of workspace_phone_numbers returns them, newest first.",
                    "value": {
                      "numbers": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "phoneNumber": "+15555550101",
                          "status": "active",
                          "source": "purchased",
                          "countryCode": "US",
                          "phoneNumberType": "local",
                          "monthlyCostCents": 675,
                          "requirementsSubmittedAt": null,
                          "pendingCancellation": false,
                          "scheduledReleaseAt": null,
                          "voiceEnabled": true,
                          "voiceMode": "ring_dashboard"
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "phoneNumber": "+15555550102",
                          "status": "active",
                          "source": "provisioned",
                          "countryCode": "US",
                          "phoneNumberType": "toll_free",
                          "monthlyCostCents": null,
                          "requirementsSubmittedAt": null,
                          "pendingCancellation": false,
                          "scheduledReleaseAt": null,
                          "voiceEnabled": false,
                          "voiceMode": "none"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The capture key belongs to no workspace, which this operation checks before anything else.",
                    "value": {
                      "error": "workspace_required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (numbers:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `number_porting` flag is off for the account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `failed_to_list`: The numbers could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "failed_to_list"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "failed_to_list",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "failed_to_list"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/numbers/available": {
      "get": {
        "operationId": "listAvailableNumbers",
        "summary": "Search numbers to buy",
        "description": "Searches the numbers on sale in a country, up to 10, priced for this account. Only numbers that can send SMS are returned. Unlike the other numbers operations, it works for a key that belongs to no workspace. Behind the `number_porting` flag: while it is off for the account, every numbers operation answers 404 `not_found`.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "numbers:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "numbers",
          "method": "listAvailable"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The ISO 3166-1 alpha-2 country code to search, in any case. Required."
            },
            "required": true,
            "name": "country",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "The number type to search for, such as `mobile`, `local` or `toll_free`. Required."
            },
            "required": true,
            "name": "type",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Digits the number must contain. Characters other than letters, digits and `*` are dropped."
            },
            "required": false,
            "name": "contains",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- AvailableNumberList: The numbers found, up to 10. Can be empty.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailableNumberList"
                },
                "examples": {
                  "default": {
                    "summary": "UK mobile numbers on sale.",
                    "value": {
                      "numbers": [
                        {
                          "phoneNumber": "+15555550100",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        },
                        {
                          "phoneNumber": "+15555550101",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        },
                        {
                          "phoneNumber": "+15555550102",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        },
                        {
                          "phoneNumber": "+15555550103",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        },
                        {
                          "phoneNumber": "+15555550104",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        },
                        {
                          "phoneNumber": "+15555550105",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        },
                        {
                          "phoneNumber": "+15555550106",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        },
                        {
                          "phoneNumber": "+15555550107",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        },
                        {
                          "phoneNumber": "+15555550108",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        },
                        {
                          "phoneNumber": "+15555550109",
                          "country": "GB",
                          "numberType": "mobile",
                          "monthlyCost": "6.75",
                          "currency": "USD"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- country and type are required: `country` or `type` is missing.\n- `domestic_not_buyable`: `country` is `US`, `PR` or `VI`, or `CA` while Canadian local buying is off. A US `local` search is allowed when US local buying is enabled for the account.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "country and type are required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "country and type are required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "domestic_not_buyable"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "domestic_not_buyable, without a message",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "domestic_not_buyable"
                      ]
                    }
                  ]
                },
                "examples": {
                  "domestic": {
                    "summary": "A Puerto Rico search, which is set up through verification instead.",
                    "value": {
                      "error": "domestic_not_buyable"
                    }
                  },
                  "default": {
                    "summary": "`type` is missing.",
                    "value": {
                      "error": "country and type are required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (numbers:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `number_porting` flag is off for the account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `search_failed`: The search failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "search_failed"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "search_failed",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "search_failed"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `search_failed`: The carrier's search failed, as it does for a number type the country does not have.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "search_failed"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Only `error`, with no `message`.",
                  "title": "search_failed",
                  "x-sendly-error-shape": "bare",
                  "x-sendly-error-codes": [
                    "search_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/numbers/buy": {
      "post": {
        "operationId": "buyNumber",
        "summary": "Buy a number",
        "description": "Buys a number from `GET /api/v1/numbers/available` for the key's workspace. The order is placed in the background, so a purchase answers 202. When a payment method or the country's documents are missing, it answers 202 with a hosted step to finish first. Needs a live key whose owner may buy numbers in the workspace. Behind the `number_porting` flag: while it is off for the account, every numbers operation answers 404 `not_found`.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "numbers:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "numbers",
          "method": "buy"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The number to buy.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuyNumberRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted.\n\n- Provisioning: The order was placed.\n- US local number provisioning: A US local number was ordered, or the workspace already owns it.\n- Payment method required: The workspace needs a payment method first.\n- Documents required: The country needs business details and documents first.\n- Under review: The documents from a completed step are in and the order was placed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BuyNumberProvisioning"
                    },
                    {
                      "$ref": "#/components/schemas/BuyUsLocalNumberProvisioning"
                    },
                    {
                      "$ref": "#/components/schemas/BuyNumberPaymentRequired"
                    },
                    {
                      "$ref": "#/components/schemas/BuyNumberDocumentsRequired"
                    },
                    {
                      "$ref": "#/components/schemas/BuyNumberUnderReview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A UK mobile number with no documents needed and a card on file: the order is placed in the background.",
                    "value": {
                      "status": "provisioning",
                      "number": {
                        "id": "00000000-0000-4000-8000-000000000001",
                        "phoneNumber": "+447700900101",
                        "status": "provisioning"
                      }
                    }
                  },
                  "payment-required": {
                    "summary": "No payment method on file: a hosted step to add one.",
                    "value": {
                      "status": "payment_required",
                      "message": "Add a payment method to complete the purchase.",
                      "action": {
                        "url": "https://sendly.live/cli-action/0123456789abcdef0123456789abcdef",
                        "code": "ABCD2345",
                        "actionCode": "0123456789abcdef0123456789abcdef",
                        "expiresAt": 1791014400000
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `workspace_required`: The API key belongs to no workspace.\n- phoneNumber is required: `phoneNumber` is missing or not a string.\n- `domestic_not_buyable`: `countryCode` is `US`, `PR` or `VI`, or `CA` while Canadian local buying is off, and the number cannot be bought as a US local number.\n- `ca_local_only`: A Canadian number whose `phoneNumberType` is not `local`.\n- `messaging_profile_required`: The workspace has not finished verification, so it has nowhere to attach the number.\n- `not_us_local`: `countryCode` is `US` but the number is in another country that shares +1.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "phoneNumber is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "phoneNumber is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "domestic_not_buyable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "domestic_not_buyable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "domestic_not_buyable"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "ca_local_only"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "ca_local_only",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "ca_local_only"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "messaging_profile_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "messaging_profile_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "messaging_profile_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "not_us_local"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "not_us_local",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "not_us_local"
                      ]
                    }
                  ]
                },
                "examples": {
                  "idempotency-key": {
                    "summary": "An Idempotency-Key longer than 255 characters.",
                    "value": {
                      "error": "invalid_idempotency_key",
                      "message": "Idempotency key must be 1-255 printable ASCII characters"
                    }
                  },
                  "default": {
                    "summary": "The capture key belongs to no workspace, which this operation checks before anything else. Nothing is ordered.",
                    "value": {
                      "error": "workspace_required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (numbers:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `live_key_required`: A test key asked to buy a number.\n- `insufficient_permission`: The key's owner has no role in the workspace that may buy numbers (`porting:write`).\n- `international_access_required`: The workspace cannot send internationally, which a number outside the US needs.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_permission"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "Singular `insufficient_permission`, unlike the `insufficient_permissions` a missing key scope gets.",
                      "title": "insufficient_permission",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_permission"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "international_access_required"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "international_access_required",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "international_access_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to buy a number.",
                    "value": {
                      "error": "live_key_required",
                      "message": "Number purchases require a live API key. Test keys can send sandbox messages from numbers you already own."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `number_porting` flag is off for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `already_owned`: The number already belongs to a workspace, this one included.\n- `already_owned`: A US local number that already belongs to another workspace.\n- `campaign_not_active`, `no_active_campaign`, `ambiguous_campaign`: A US local number: `campaignId` is not an active campaign of the workspace (`campaign_not_active`), or `allowUnregistered` is `false` and the workspace has no active campaign (`no_active_campaign`) or more than one (`ambiguous_campaign`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "already_owned"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "already_owned, without a message",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "already_owned"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "already_owned"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "already_owned",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "already_owned"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "campaign_not_active",
                            "no_active_campaign",
                            "ambiguous_campaign"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "campaign_not_active, no_active_campaign, ambiguous_campaign",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "campaign_not_active",
                        "no_active_campaign",
                        "ambiguous_campaign"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `buy_failed`: The purchase failed unexpectedly. A US local purchase that fails here was not charged.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "buy_failed"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "buy_failed",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "buy_failed"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `pricing_unavailable`: The number could not be priced right now. Nothing was ordered: try again.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "pricing_unavailable"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "pricing_unavailable",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "pricing_unavailable"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/numbers/countries": {
      "get": {
        "operationId": "listNumberCountries",
        "summary": "List countries to buy numbers in",
        "description": "Lists the countries where this workspace can buy a number right now, with the number types on sale. A country is listed only when it has SMS-capable numbers in stock and the workspace can send there: international access for numbers outside the US, and the US and Canada only when local buying is enabled for the account. Behind the `number_porting` flag: while it is off for the account, every numbers operation answers 404 `not_found`.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "numbers:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "numbers",
          "method": "listCountries"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- NumberCountryList: The countries the workspace can buy numbers in. Can be empty.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NumberCountryList"
                },
                "examples": {
                  "default": {
                    "summary": "The countries the workspace can buy numbers in, from computeCountryCapabilities filtered to canBuy.",
                    "value": {
                      "countries": [
                        {
                          "code": "GB",
                          "name": "United Kingdom",
                          "numberTypes": [
                            "mobile"
                          ]
                        },
                        {
                          "code": "NL",
                          "name": "Netherlands",
                          "numberTypes": [
                            "mobile"
                          ]
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The capture key belongs to no workspace, which this operation checks before anything else.",
                    "value": {
                      "error": "workspace_required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (numbers:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `number_porting` flag is off for the account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `failed_to_load_countries`: The countries could not be worked out.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "failed_to_load_countries"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "failed_to_load_countries",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "failed_to_load_countries"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `coverage_unavailable`: The carrier's coverage could not be loaded, and no earlier copy is cached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "coverage_unavailable"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Only `error`, with no `message`.",
                  "title": "coverage_unavailable",
                  "x-sendly-error-shape": "bare",
                  "x-sendly-error-codes": [
                    "coverage_unavailable"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/numbers/{id}": {
      "get": {
        "operationId": "getNumber",
        "summary": "Get a number",
        "description": "Returns one number the key's workspace owns. Behind the `number_porting` flag: while it is off for the account, every numbers operation answers 404 `not_found`.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "numbers:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "numbers",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The number's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- PhoneNumber: The number.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneNumber"
                },
                "examples": {
                  "default": {
                    "summary": "One number, as the handler's projection returns it, with isDefault.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "phoneNumber": "+15555550101",
                      "status": "active",
                      "source": "purchased",
                      "countryCode": "US",
                      "phoneNumberType": "local",
                      "monthlyCostCents": 675,
                      "isDefault": true,
                      "requirementsSubmittedAt": null,
                      "pendingCancellation": false,
                      "scheduledReleaseAt": null,
                      "voiceEnabled": true,
                      "voiceMode": "ring_dashboard"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The capture key belongs to no workspace, which this operation checks before anything else.",
                    "value": {
                      "error": "workspace_required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (numbers:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `number_porting` flag is off for the account, or no number with this id belongs to the key's workspace, or the number was released.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no number of the key's workspace.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `failed_to_get`: The number could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "failed_to_get"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "failed_to_get",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "failed_to_get"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateNumber",
        "summary": "Update a number",
        "description": "Makes a number the workspace's default sender, or keeps a number whose release was scheduled. Behind the `number_porting` flag: while it is off for the account, every numbers operation answers 404 `not_found`.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "numbers:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "numbers",
          "method": "update"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The number's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "What to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateNumberRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- UpdatedPhoneNumber: The number, as it is after the change.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdatedPhoneNumber"
                },
                "examples": {
                  "default": {
                    "summary": "`isDefault: true` on an active number: the fresh projection, without voiceEnabled and voiceMode.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "phoneNumber": "+15555550101",
                      "status": "active",
                      "source": "purchased",
                      "countryCode": "US",
                      "phoneNumberType": "local",
                      "monthlyCostCents": 675,
                      "isDefault": true,
                      "requirementsSubmittedAt": null,
                      "pendingCancellation": false,
                      "scheduledReleaseAt": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace.\n- `no_supported_fields`: The body has neither `isDefault: true` nor `pendingCancellation: false`.\n- `invalid_state`: `isDefault: true` for a number that is not `active`.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_supported_fields"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "no_supported_fields",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_supported_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_state"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_state",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_state"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The capture key belongs to no workspace, which this operation checks before anything else.",
                    "value": {
                      "error": "workspace_required"
                    }
                  },
                  "no-supported-fields": {
                    "summary": "A body with neither supported field.",
                    "value": {
                      "error": "no_supported_fields",
                      "message": "Supported updates: { isDefault: true } or { pendingCancellation: false }."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (numbers:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `number_porting` flag is off for the account, or no number with this id belongs to the key's workspace, or the number was released.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `failed_to_update`: The number could not be updated.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "failed_to_update"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "failed_to_update",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "failed_to_update"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "releaseNumber",
        "summary": "Release a number",
        "description": "Releases a number the key's workspace owns. An active number bought and paid for here is kept until the end of the month and then released; calling this again before then releases it at once. Any other number is released at once and leaves the workspace: a number bought here has its pending carrier order cancelled or is released at the carrier, a hosted number stops being hosted, and its documents are deleted. It needs a live key (a CLI session may release too) whose user's role in the workspace has the `porting:write` permission. Behind the `number_porting` flag: while it is off for the account, every numbers operation answers 404 `not_found`.",
        "tags": [
          "Phone numbers"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "numbers:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "numbers",
          "method": "release"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The number's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Release scheduled: An active, paid number bought here, with no release scheduled yet: the release is scheduled for the end of the month.\n- Released: The number was released.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/NumberReleaseScheduled"
                    },
                    {
                      "$ref": "#/components/schemas/NumberReleased"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A number that is not an active paid purchase, released at once.",
                    "value": {
                      "success": true
                    }
                  },
                  "scheduled": {
                    "summary": "An active, paid number bought here: the release is scheduled for the last second of the month.",
                    "value": {
                      "success": true,
                      "scheduled": true,
                      "scheduledReleaseAt": "2026-10-31T23:59:59.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The key belongs to no workspace.\n- Release refused by the carrier: The carrier refused to release the number or to stop hosting it. The number is kept.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "release_failed"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds the carrier's own error text, or `Failed to release hosted number` or `Failed to release toll-free number` when it gave none, and there is no `message`.",
                      "title": "Release refused by the carrier",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "release_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The capture key belongs to no workspace, which this operation checks before anything else. The id matches no number, so nothing could be released.",
                    "value": {
                      "error": "workspace_required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (numbers:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `live_key_required`: A test API key called it. A CLI session may release a number.\n- `insufficient_permission`: The key's user has no role in the workspace, or a role without the `porting:write` permission.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_permission"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "Singular `insufficient_permission`, unlike the `insufficient_permissions` a missing key scope gets.",
                      "title": "insufficient_permission",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_permission"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Number management is not enabled for the account.\n- `not_found`: No number with this id belongs to the key's workspace, or the number was already released.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no number of the key's workspace.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- Release failed: The checks could not be run.\n- Release failed: The release failed unexpectedly, possibly part way.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/NumberReleaseServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/port": {
      "get": {
        "operationId": "listPorts",
        "summary": "List port requests",
        "description": "Lists the workspace's port requests, newest first, with no paging. Behind the `porting_headless` flag: without it every port route answers 404.",
        "tags": [
          "Number porting"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "How many to return, 1 to 200. Defaults to 50, which is also what 0 or a value that is not a number gives. A value below 1 is raised to 1, and one above 200 is lowered to 200."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- PortList: The workspace's port requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortList"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. `listHeadlessPorts` maps each row through `publicPort`.",
                    "value": {
                      "ports": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "phoneNumber": "+15555550100",
                          "portType": "full_port",
                          "status": "draft",
                          "statusDetail": null,
                          "focRequested": null,
                          "focActual": null,
                          "loaSigned": false,
                          "documentsUploaded": false,
                          "verificationSubmitted": false,
                          "submittedAt": null,
                          "completedAt": null,
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Headless porting is not enabled for the caller's account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "The capture account does not have the `porting_headless` flag, so the route answers 404.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createPort",
        "summary": "Create a port request",
        "description": "Starts a full port of one US or Canada number: creates a draft porting order with the carrier and records the request. Nothing goes to the losing carrier until `POST /api/v1/port/{id}/submit`, and that needs the authorization signed and the documents uploaded through the secure porting form first. A test key is not simulated here. Behind the `porting_headless` flag: without it every port route answers 404.",
        "tags": [
          "Number porting"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "requestBody": {
          "description": "The number to port and who authorizes it.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePortRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- PortCreated: The draft porting order was created and recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortCreated"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. A port request is never created by a capture. The handler answers with the new id, the draft order's status and `full_port`.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "status": "draft",
                      "portType": "full_port"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `port_type_unsupported`: `portType` is missing or is not `full_port`.\n- `invalid_phone_number`: `phoneNumber` is missing, or is not a US, Canada or toll-free number in E.164 format.\n- `auth_person_required`: `authPersonName` or `authPersonEmail` is missing or empty.\n- `messaging_profile_required`: The workspace has not been verified, so it has no messaging profile to port into.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "port_type_unsupported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "port_type_unsupported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "port_type_unsupported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_phone_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_phone_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_phone_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "auth_person_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "auth_person_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "auth_person_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "messaging_profile_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "messaging_profile_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "messaging_profile_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-phone-number": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. A number that is not a US or Canada number in E.164 format.",
                    "value": {
                      "error": "invalid_phone_number",
                      "message": "A portable US or Canada number is required."
                    }
                  },
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. No `portType`.",
                    "value": {
                      "error": "port_type_unsupported",
                      "message": "This surface currently supports portType: \"full_port\" only."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `payment_method_required`: The workspace has no payment method on file, or it could not be checked. Checked before the body. Enterprise-billed workspaces skip this.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "payment_method_required"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "actionUrl": {
                      "type": "string",
                      "enum": [
                        "/billing"
                      ]
                    },
                    "feature": {
                      "type": "string",
                      "enum": [
                        "port_request"
                      ]
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "actionUrl",
                    "feature"
                  ],
                  "title": "payment_method_required",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "payment_method_required"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. The workspace has no payment method on file.",
                    "value": {
                      "error": "payment_method_required",
                      "message": "A payment method is required to submit a port request. Please add one in your billing settings.",
                      "actionUrl": "/billing",
                      "feature": "port_request"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permission`: The caller is not an active member of the workspace, or their role is not `owner` or `admin`, the roles with the `porting:write` permission.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_permission"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "insufficient_permission",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "insufficient_permission"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Headless porting is not enabled for the caller's account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "A body with no `portType`, which would be refused with a 400 before anything is created. The capture account does not have the `porting_headless` flag, so the route answers 404 first.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `duplicate_port_request`: The workspace already has a port request for this number that is not final.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "duplicate_port_request"
                      ]
                    },
                    "existingPortId": {
                      "type": "string",
                      "description": "The workspace's open port request for this number."
                    }
                  },
                  "required": [
                    "error",
                    "existingPortId"
                  ],
                  "description": "`error` and `existingPortId`, with no `message`.",
                  "title": "duplicate_port_request",
                  "x-sendly-error-shape": "bare",
                  "x-sendly-error-codes": [
                    "duplicate_port_request"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. The workspace already has an open port request for this number.",
                    "value": {
                      "error": "duplicate_port_request",
                      "existingPortId": "00000000-0000-4000-8000-000000000002"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `port_record_failed`: The draft order was created but the request could not be recorded. Nothing was submitted.\n- `internal_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "port_record_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "port_record_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "port_record_failed"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `carrier_order_failed`: The carrier did not create the draft porting order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "carrier_order_failed"
                      ]
                    },
                    "message": {
                      "type": "string",
                      "description": "The carrier's reason. Absent when the carrier answered without an order id."
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "title": "carrier_order_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "carrier_order_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/port/check": {
      "post": {
        "operationId": "checkPortability",
        "summary": "Check whether numbers can be ported",
        "description": "Asks the carrier whether each number can be ported in. Read-only: it creates nothing. Behind the `porting_headless` flag: without it every port route answers 404.",
        "tags": [
          "Number porting"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "requestBody": {
          "description": "The numbers to check.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckPortabilityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- PortabilityResults: One result per number.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortabilityResults"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. `headlessCheckPortability` returns the carrier's results as `checkPortability` maps them.",
                    "value": {
                      "results": [
                        {
                          "phone_number": "+15555550100",
                          "portable": true,
                          "carrier_name": "Example Carrier",
                          "phone_number_type": "local",
                          "fast_portable": true,
                          "messaging_capable": true,
                          "not_portable_reason": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `phone_numbers_required`: `phoneNumbers` is an empty array, or it is not an array and `phoneNumber` is missing or empty.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "phone_numbers_required"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "phone_numbers_required",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "phone_numbers_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. No numbers to check.",
                    "value": {
                      "error": "phone_numbers_required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Headless porting is not enabled for the caller's account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "One fictional number. The capture account does not have the `porting_headless` flag, so the route answers 404 before it checks anything.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `portability_check_failed`: The carrier's portability check failed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "portability_check_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "portability_check_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "portability_check_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/port/{id}": {
      "get": {
        "operationId": "getPort",
        "summary": "Get a port request",
        "description": "Returns one port request of the workspace. Behind the `porting_headless` flag: without it every port route answers 404.",
        "tags": [
          "Number porting"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The port request's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- PortResponse: The port request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortResponse"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. `getHeadlessPort` returns `{ port: publicPort(row) }`.",
                    "value": {
                      "port": {
                        "id": "00000000-0000-4000-8000-000000000001",
                        "phoneNumber": "+15555550100",
                        "portType": "full_port",
                        "status": "draft",
                        "statusDetail": null,
                        "focRequested": null,
                        "focActual": null,
                        "loaSigned": false,
                        "documentsUploaded": false,
                        "verificationSubmitted": false,
                        "submittedAt": null,
                        "completedAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Headless porting is not enabled for the caller's account, or no port request with this id belongs to the workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no port request. The capture account does not have the `porting_headless` flag, so the route answers 404 before it looks.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "cancelPort",
        "summary": "Cancel a port request",
        "description": "Cancels a port request that is not final, and its carrier porting order. Behind the `porting_headless` flag: without it every port route answers 404.",
        "tags": [
          "Number porting"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The port request's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- CancelledPort: The port request was cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelledPort"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. A port request is never cancelled by a capture. `cancelHeadlessPort` answers with the id and `cancelled`.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "status": "cancelled"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permission`: The caller is not an active member of the workspace, or their role is not `owner` or `admin`, the roles with the `porting:write` permission.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_permission"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "insufficient_permission",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "insufficient_permission"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Headless porting is not enabled for the caller's account, or no port request with this id belongs to the workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no port request, so nothing is cancelled. The capture account does not have the `porting_headless` flag, so the route answers 404 before it looks.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `not_cancellable`: The port is already final; `message` names its status.\n- `hosted_cancel_unsupported`: A port that is not a `full_port`, such as a `hosted_sms` port, which this API cannot cancel yet: cancel it from the dashboard.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "not_cancellable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "not_cancellable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "not_cancellable"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "hosted_cancel_unsupported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "hosted_cancel_unsupported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "hosted_cancel_unsupported"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. The port is already final.",
                    "value": {
                      "error": "not_cancellable",
                      "message": "Port is already cancelled."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `carrier_cancel_failed`: The carrier did not cancel the porting order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "carrier_cancel_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "carrier_cancel_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "carrier_cancel_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/port/{id}/submit": {
      "post": {
        "operationId": "submitPort",
        "summary": "Submit a port request",
        "description": "Confirms the carrier porting order, which sends it to the losing carrier. This cannot be undone. The letter of authorization must be signed through the secure porting form, and a full port needs its authorization document, a recent invoice and the losing carrier's account number. A test key is not simulated here. Behind the `porting_headless` flag: without it every port route answers 404.",
        "tags": [
          "Number porting"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The port request's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- SubmittedPort: The porting order was confirmed with the carrier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittedPort"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. A port is never submitted by a capture. `submitHeadlessPort` answers with the carrier order's new status.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "status": "in-process",
                      "submitted": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permission`: The caller is not an active member of the workspace, or their role is not `owner` or `admin`, the roles with the `porting:write` permission.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_permission"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "insufficient_permission",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "insufficient_permission"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: Headless porting is not enabled for the caller's account, or no port request with this id belongs to the workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no port request, so nothing is submitted. The capture account does not have the `porting_headless` flag, so the route answers 404 before it looks.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `already_submitted`: The port was already submitted.\n- `not_submittable`: The port is final; `message` names its status.\n- `requirements_incomplete`: The secure porting form is not finished: `missing` lists what it still needs.\n- `hosted_submit_unsupported`: A port that is not a `full_port`, such as a `hosted_sms` port, which this API cannot submit yet. Checked after the requirements.\n- `no_carrier_order`: The port request has no carrier porting order.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "already_submitted"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "already_submitted",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "already_submitted"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "not_submittable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "not_submittable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "not_submittable"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "requirements_incomplete"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "missing": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "description": "What the secure porting form still needs. Known values: `loa_signature`, `loa_document`, `recent_invoice`, `losing_carrier_account_number`. More can be added at any time, so treat an unknown value as valid.",
                            "x-sendly-extensible-enum": [
                              "loa_signature",
                              "loa_document",
                              "recent_invoice",
                              "losing_carrier_account_number"
                            ]
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "missing"
                      ],
                      "title": "requirements_incomplete",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "requirements_incomplete"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "hosted_submit_unsupported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "hosted_submit_unsupported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "hosted_submit_unsupported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_carrier_order"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "no_carrier_order",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "no_carrier_order"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture account does not have the `porting_headless` flag. The authorization is not signed and the documents are not uploaded.",
                    "value": {
                      "error": "requirements_incomplete",
                      "missing": [
                        "loa_signature",
                        "loa_document",
                        "recent_invoice",
                        "losing_carrier_account_number"
                      ],
                      "message": "Finish the secure porting form (sign the authorization and upload the required documents) before submitting."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `carrier_submit_failed`: The carrier did not confirm the porting order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "carrier_submit_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "carrier_submit_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "carrier_submit_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/agents": {
      "get": {
        "operationId": "listRcsAgents",
        "summary": "List RCS agents",
        "description": "Lists the workspace's RCS agents, newest first, with whether each can send now. An API key needs `rcs:read` or `sms:send`.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.agents",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- The workspace's agents.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agents": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RcsAgentSummary"
                      }
                    }
                  },
                  "required": [
                    "agents"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #217 (40274da1) each agent also carries `displayName` and `customerStage`, copies of `name` and `stage`. The production capture of 2026-10-03 predates that change. It was: The test account's agents: one draft.",
                    "value": {
                      "agents": [
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "name": "",
                          "displayName": "",
                          "status": "draft",
                          "useCase": "TRANSACTIONAL",
                          "sendable": false,
                          "stage": "draft",
                          "customerStage": "draft",
                          "createdAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key holds neither `rcs:read` nor `sms:send`. A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RcsNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createRcsAgent",
        "summary": "Create an RCS agent",
        "description": "Creates an agent draft for a brand. Its fields are checked when it is submitted for review.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.agents",
          "method": "create"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The agent.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRcsAgentRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- The agent draft was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agent": {
                      "$ref": "#/components/schemas/RcsAgent"
                    }
                  },
                  "required": [
                    "agent"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An agent draft for a brand, built from createRcsAgent and toPublicRcsAgent: creating one in production would change the test account's registration.",
                    "value": {
                      "agent": {
                        "id": "00000000-0000-4000-8000-000000000002",
                        "brandId": "00000000-0000-4000-8000-000000000001",
                        "status": "draft",
                        "reviewStatus": "draft",
                        "customerStage": "draft",
                        "displayName": "Example Coffee",
                        "useCase": "TRANSACTIONAL",
                        "hostingRegion": null,
                        "basics": {
                          "description": "Order updates from Example Coffee.",
                          "logoUrl": "https://www.example.com/rcs/logo.png",
                          "heroUrl": "https://www.example.com/rcs/hero.png",
                          "brandColor": "#2563EB",
                          "privacyPolicyUrl": "https://www.example.com/privacy",
                          "termsAndConditionsUrl": "https://www.example.com/terms",
                          "phoneNumber": {
                            "number": "+15555550101",
                            "label": "Call us"
                          },
                          "website": {
                            "url": "https://www.example.com",
                            "label": "Website"
                          },
                          "email": {
                            "address": "user@example.com",
                            "label": "Email us"
                          },
                          "displayName": "Example Coffee",
                          "useCase": "TRANSACTIONAL",
                          "hostingRegion": null
                        },
                        "campaign": null,
                        "testing": null,
                        "reviewNote": null,
                        "rejectionReason": null,
                        "testDevices": [],
                        "submittedForReviewAt": null,
                        "basicsSubmittedAt": null,
                        "launchSubmittedAt": null,
                        "liveAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:write` permission for RCS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.\n- `rcs_not_found`: No brand with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RcsNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_found"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A brandId that matches no brand.",
                    "value": {
                      "error": "rcs_not_found",
                      "message": "No RCS brand with that id is set up on this workspace."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `rcs_invalid_content`: `basics.logoUrl`, `basics.heroUrl` or `campaign.consentSettings.callToActionMediaUrl` is not a public `https://` URL.\n- `rcs_invalid_content`: `brandId` is missing.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_invalid_content"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/RcsValidationIssue"
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errors"
                      ],
                      "title": "rcs_invalid_content, with the fields",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_invalid_content"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "asset-url": {
                    "summary": "A logo URL that is not https, refused before anything is stored.",
                    "value": {
                      "error": "rcs_invalid_content",
                      "message": "Assets can't be uploaded over the API. Logo, hero, and call-to-action media must be public https:// URLs.",
                      "errors": [
                        {
                          "path": "basics.logoUrl",
                          "message": "Must be a public https:// URL"
                        }
                      ]
                    }
                  },
                  "default": {
                    "summary": "No brandId, refused before anything is stored.",
                    "value": {
                      "error": "rcs_invalid_content",
                      "message": "Some registration fields need attention before this can continue.",
                      "errors": [
                        {
                          "path": "brandId",
                          "message": "Choose a brand for this agent"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/agents/{id}": {
      "get": {
        "operationId": "getRcsAgent",
        "summary": "Get an RCS agent",
        "description": "Returns one agent of the workspace, with its test devices and stage.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.agents",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The agent's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The agent. `devices` repeats `agent.testDevices`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agent": {
                      "$ref": "#/components/schemas/RcsAgent"
                    },
                    "devices": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RcsTestDevice"
                      }
                    },
                    "stage": {
                      "type": "string",
                      "description": "Where the registration is, in customer terms. Known values: `draft`, `in_review`, `changes_requested`, `rejected`, `brand_verification`, `agent_review`, `testing`, `launch_review`, `launching`, `launch_rejected`, `live`, `suspended`, `failed`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "draft",
                        "in_review",
                        "changes_requested",
                        "rejected",
                        "brand_verification",
                        "agent_review",
                        "testing",
                        "launch_review",
                        "launching",
                        "launch_rejected",
                        "live",
                        "suspended",
                        "failed"
                      ]
                    }
                  },
                  "required": [
                    "agent",
                    "devices",
                    "stage"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The test account's draft agent.",
                    "value": {
                      "agent": {
                        "id": "00000000-0000-4000-8000-000000000002",
                        "brandId": "00000000-0000-4000-8000-000000000001",
                        "status": "draft",
                        "reviewStatus": "draft",
                        "customerStage": "draft",
                        "displayName": "",
                        "useCase": "TRANSACTIONAL",
                        "hostingRegion": null,
                        "basics": {
                          "email": null,
                          "heroUrl": "https://assets.sendly.live/brand-assets/rcs/00000000-0000-4000-8000-000000000003/hero-00000000-0000-4000-8000-000000000004.png",
                          "logoUrl": "https://assets.sendly.live/brand-assets/rcs/00000000-0000-4000-8000-000000000003/logo-00000000-0000-4000-8000-000000000005.png",
                          "website": null,
                          "brandColor": "#2563EB",
                          "description": "",
                          "phoneNumber": null,
                          "privacyPolicyUrl": "",
                          "termsAndConditionsUrl": "",
                          "displayName": "",
                          "useCase": "TRANSACTIONAL",
                          "hostingRegion": null
                        },
                        "campaign": {
                          "interactions": [],
                          "agentOverview": "",
                          "companyOverview": "",
                          "consentSettings": {
                            "doubleOptIn": false,
                            "callToAction": "",
                            "helpResponse": "",
                            "optInMessage": "",
                            "optInMethods": [],
                            "optOutResponse": "",
                            "callToActionUrl": null,
                            "doubleOptInMessage": null,
                            "callToActionMediaUrl": null
                          },
                          "messageExamples": [],
                          "additionalInformation": null
                        },
                        "testing": null,
                        "reviewNote": null,
                        "rejectionReason": null,
                        "testDevices": [],
                        "submittedForReviewAt": null,
                        "basicsSubmittedAt": null,
                        "launchSubmittedAt": null,
                        "liveAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      },
                      "devices": [],
                      "stage": "draft"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:read` permission for RCS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.\n- `rcs_not_found`: No agent with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RcsNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_found"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no agent.",
                    "value": {
                      "error": "rcs_not_found",
                      "message": "No RCS agent with that id is set up on this workspace."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateRcsAgent",
        "summary": "Update an RCS agent",
        "description": "Changes an agent's profile, campaign or testing details. The profile locks once the registration is approved; the campaign and testing details lock once the launch is sent, until it is rejected.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.agents",
          "method": "update"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The agent's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateRcsAgentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- The agent, changed. A body with nothing to change returns it as is.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agent": {
                      "$ref": "#/components/schemas/RcsAgent"
                    }
                  },
                  "required": [
                    "agent"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An empty patch on the test account's draft agent, which returns it unchanged.",
                    "value": {
                      "agent": {
                        "id": "00000000-0000-4000-8000-000000000002",
                        "brandId": "00000000-0000-4000-8000-000000000001",
                        "status": "draft",
                        "reviewStatus": "draft",
                        "customerStage": "draft",
                        "displayName": "",
                        "useCase": "TRANSACTIONAL",
                        "hostingRegion": null,
                        "basics": {
                          "email": null,
                          "heroUrl": "https://assets.sendly.live/brand-assets/rcs/00000000-0000-4000-8000-000000000003/hero-00000000-0000-4000-8000-000000000004.png",
                          "logoUrl": "https://assets.sendly.live/brand-assets/rcs/00000000-0000-4000-8000-000000000003/logo-00000000-0000-4000-8000-000000000005.png",
                          "website": null,
                          "brandColor": "#2563EB",
                          "description": "",
                          "phoneNumber": null,
                          "privacyPolicyUrl": "",
                          "termsAndConditionsUrl": "",
                          "displayName": "",
                          "useCase": "TRANSACTIONAL",
                          "hostingRegion": null
                        },
                        "campaign": {
                          "interactions": [],
                          "agentOverview": "",
                          "companyOverview": "",
                          "consentSettings": {
                            "doubleOptIn": false,
                            "callToAction": "",
                            "helpResponse": "",
                            "optInMessage": "",
                            "optInMethods": [],
                            "optOutResponse": "",
                            "callToActionUrl": null,
                            "doubleOptInMessage": null,
                            "callToActionMediaUrl": null
                          },
                          "messageExamples": [],
                          "additionalInformation": null
                        },
                        "testing": null,
                        "reviewNote": null,
                        "rejectionReason": null,
                        "testDevices": [],
                        "submittedForReviewAt": null,
                        "basicsSubmittedAt": null,
                        "launchSubmittedAt": null,
                        "liveAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:write` permission for RCS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.\n- `rcs_not_found`: No agent with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RcsNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_found"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no agent.",
                    "value": {
                      "error": "rcs_not_found",
                      "message": "No RCS agent with that id is set up on this workspace."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `rcs_field_locked`: The registration is in review (`awaiting_review` or `launch_requested`); or the profile was sent while the agent is approved or already sent to the carrier network; or the campaign or testing details were sent after the launch went to the carrier network.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "rcs_field_locked"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "rcs_field_locked",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "rcs_field_locked"
                  ],
                  "x-sendly-visibility": "preview"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `rcs_invalid_content`: `basics.logoUrl`, `basics.heroUrl` or `campaign.consentSettings.callToActionMediaUrl` is not a public `https://` URL.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_invalid_content"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/RcsValidationIssue"
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errors"
                      ],
                      "title": "rcs_invalid_content, with the fields",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_invalid_content"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/agents/{id}/request-launch": {
      "post": {
        "operationId": "requestRcsAgentLaunch",
        "summary": "Request an RCS agent's launch",
        "description": "Asks Sendly to launch an agent that finished testing, for review before it goes to the carrier network.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.agents",
          "method": "requestLaunch"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The agent's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "Testing details to store first.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RequestRcsLaunchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- The launch is awaiting review (`launch_requested`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agent": {
                      "$ref": "#/components/schemas/RcsAgent"
                    },
                    "stage": {
                      "type": "string",
                      "description": "Where the registration is, in customer terms. Known values: `draft`, `in_review`, `changes_requested`, `rejected`, `brand_verification`, `agent_review`, `testing`, `launch_review`, `launching`, `launch_rejected`, `live`, `suspended`, `failed`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "draft",
                        "in_review",
                        "changes_requested",
                        "rejected",
                        "brand_verification",
                        "agent_review",
                        "testing",
                        "launch_review",
                        "launching",
                        "launch_rejected",
                        "live",
                        "suspended",
                        "failed"
                      ]
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RcsValidationIssue"
                      },
                      "description": "Launch fields that pass but may slow the review."
                    }
                  },
                  "required": [
                    "agent",
                    "stage",
                    "warnings"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A launch request for an agent in testing, built from requestRcsAgentLaunch: requesting one in production would start a real launch review.",
                    "value": {
                      "agent": {
                        "id": "00000000-0000-4000-8000-000000000002",
                        "brandId": "00000000-0000-4000-8000-000000000001",
                        "status": "testing",
                        "reviewStatus": "launch_requested",
                        "customerStage": "launch_review",
                        "displayName": "Example Coffee",
                        "useCase": "TRANSACTIONAL",
                        "hostingRegion": null,
                        "basics": {
                          "description": "Order updates from Example Coffee.",
                          "logoUrl": "https://www.example.com/rcs/logo.png",
                          "heroUrl": "https://www.example.com/rcs/hero.png",
                          "brandColor": "#2563EB",
                          "privacyPolicyUrl": "https://www.example.com/privacy",
                          "termsAndConditionsUrl": "https://www.example.com/terms",
                          "phoneNumber": {
                            "number": "+15555550101",
                            "label": "Call us"
                          },
                          "website": {
                            "url": "https://www.example.com",
                            "label": "Website"
                          },
                          "email": {
                            "address": "user@example.com",
                            "label": "Email us"
                          },
                          "displayName": "Example Coffee",
                          "useCase": "TRANSACTIONAL",
                          "hostingRegion": null
                        },
                        "campaign": {
                          "companyOverview": "Example Coffee runs 12 cafes in Chicago.",
                          "agentOverview": "Sends order-ready alerts and answers questions about orders.",
                          "interactions": [
                            {
                              "interactionType": "TRANSACTIONAL_UPDATES",
                              "description": "Order-ready alerts."
                            }
                          ],
                          "messageExamples": [
                            "Your order is ready at the Main St cafe.",
                            "Your order was picked up. Thanks!",
                            "Reply HELP for help or STOP to opt out."
                          ],
                          "consentSettings": {
                            "optInMethods": [
                              {
                                "methodType": "WEBSITE",
                                "description": "A checkbox at checkout."
                              }
                            ],
                            "callToAction": "Check the box to get order updates by RCS.",
                            "callToActionUrl": "https://www.example.com/checkout",
                            "callToActionMediaUrl": "https://www.example.com/rcs/checkout.png",
                            "doubleOptIn": false,
                            "optInMessage": "You're subscribed to Example Coffee order updates. Reply STOP to opt out.",
                            "helpResponse": "Example Coffee: email user@example.com for help. Reply STOP to opt out.",
                            "optOutResponse": "You're unsubscribed from Example Coffee. No more messages will be sent."
                          },
                          "additionalInformation": null
                        },
                        "testing": {
                          "testUrl": "https://www.example.com/rcs-test",
                          "additionalInformation": "Tested on two devices."
                        },
                        "reviewNote": null,
                        "rejectionReason": null,
                        "testDevices": [
                          {
                            "id": "00000000-0000-4000-8000-000000000006",
                            "phoneNumber": "+15555550102",
                            "label": "Test phone",
                            "inviteStatus": "ACCEPTED",
                            "createdAt": "2026-01-01T00:00:00.000Z"
                          }
                        ],
                        "submittedForReviewAt": "2026-01-01T00:00:00.000Z",
                        "basicsSubmittedAt": "2026-01-01T00:00:00.000Z",
                        "launchSubmittedAt": null,
                        "liveAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      },
                      "stage": "launch_review",
                      "warnings": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:write` permission for RCS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.\n- `rcs_not_found`: No agent with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RcsNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_found"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no agent.",
                    "value": {
                      "error": "rcs_not_found",
                      "message": "No RCS agent with that id is set up on this workspace."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `rcs_field_locked`: The registration is in review (`awaiting_review` or `launch_requested`).\n- `rcs_launch_not_ready`: The agent is not approved for the carrier network or launch-rejected, or is not in testing.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_field_locked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_field_locked",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_field_locked"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_launch_not_ready"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_launch_not_ready",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_launch_not_ready"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `rcs_invalid_content`: The campaign or testing details fail the launch checks.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_invalid_content"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/RcsValidationIssue"
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errors"
                      ],
                      "title": "rcs_invalid_content, with the fields",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_invalid_content"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/agents/{id}/submit": {
      "post": {
        "operationId": "submitRcsAgent",
        "summary": "Submit an RCS agent for review",
        "description": "Checks the agent and its brand, and submits both for Sendly's review. The workspace's business must be verified first.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.agents",
          "method": "submit"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The agent's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- The agent and its brand are awaiting review.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agent": {
                      "$ref": "#/components/schemas/RcsAgent"
                    },
                    "stage": {
                      "type": "string",
                      "description": "Where the registration is, in customer terms. Known values: `draft`, `in_review`, `changes_requested`, `rejected`, `brand_verification`, `agent_review`, `testing`, `launch_review`, `launching`, `launch_rejected`, `live`, `suspended`, `failed`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "draft",
                        "in_review",
                        "changes_requested",
                        "rejected",
                        "brand_verification",
                        "agent_review",
                        "testing",
                        "launch_review",
                        "launching",
                        "launch_rejected",
                        "live",
                        "suspended",
                        "failed"
                      ]
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RcsValidationIssue"
                      },
                      "description": "Fields that pass but may slow the review."
                    }
                  },
                  "required": [
                    "agent",
                    "stage",
                    "warnings"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An agent submitted for review, built from submitRcsAgent: submitting in production would start a real review.",
                    "value": {
                      "agent": {
                        "id": "00000000-0000-4000-8000-000000000002",
                        "brandId": "00000000-0000-4000-8000-000000000001",
                        "status": "draft",
                        "reviewStatus": "awaiting_review",
                        "customerStage": "in_review",
                        "displayName": "Example Coffee",
                        "useCase": "TRANSACTIONAL",
                        "hostingRegion": null,
                        "basics": {
                          "description": "Order updates from Example Coffee.",
                          "logoUrl": "https://www.example.com/rcs/logo.png",
                          "heroUrl": "https://www.example.com/rcs/hero.png",
                          "brandColor": "#2563EB",
                          "privacyPolicyUrl": "https://www.example.com/privacy",
                          "termsAndConditionsUrl": "https://www.example.com/terms",
                          "phoneNumber": {
                            "number": "+15555550101",
                            "label": "Call us"
                          },
                          "website": {
                            "url": "https://www.example.com",
                            "label": "Website"
                          },
                          "email": {
                            "address": "user@example.com",
                            "label": "Email us"
                          },
                          "displayName": "Example Coffee",
                          "useCase": "TRANSACTIONAL",
                          "hostingRegion": null
                        },
                        "campaign": null,
                        "testing": null,
                        "reviewNote": null,
                        "rejectionReason": null,
                        "testDevices": [],
                        "submittedForReviewAt": "2026-01-01T00:00:00.000Z",
                        "basicsSubmittedAt": null,
                        "launchSubmittedAt": null,
                        "liveAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      },
                      "stage": "in_review",
                      "warnings": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:write` permission for RCS.\n- `verification_required`: The workspace's business is not verified yet.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "verification_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "verification_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "verification_required"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.\n- `rcs_not_found`: No agent with this id belongs to the workspace.\n- `rcs_not_found`: The agent's brand no longer belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RcsNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_found"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no agent.",
                    "value": {
                      "error": "rcs_not_found",
                      "message": "No RCS agent with that id is set up on this workspace."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `rcs_field_locked`: The agent was already submitted, rejected or failed, or its brand was rejected in review.\n- `rcs_brand_not_verified`: The brand failed carrier verification.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_field_locked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_field_locked",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_field_locked"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_brand_not_verified"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_brand_not_verified",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_brand_not_verified"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `rcs_invalid_content`: The agent has no brand (path `brandId`), or brand or agent fields fail the checks (paths start with `brand.` or `agent.`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_invalid_content"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/RcsValidationIssue"
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errors"
                      ],
                      "title": "rcs_invalid_content, with the fields",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_invalid_content"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/agents/{id}/test-devices": {
      "put": {
        "operationId": "setRcsAgentTestDevices",
        "summary": "Set an RCS agent's test devices",
        "description": "Replaces the agent's test devices with the list sent: devices not in it are removed, new ones added. Once the agent is in testing, new devices are invited at once.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.agents",
          "method": "setTestDevices"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The agent's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "Every test device the agent should have.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetRcsTestDevicesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- The agent's test devices now.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "devices": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RcsTestDevice"
                      }
                    }
                  },
                  "required": [
                    "devices"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An empty list for the test account's draft agent, which has no test devices, so nothing changes.",
                    "value": {
                      "devices": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:write` permission for RCS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.\n- `rcs_not_found`: No agent with this id belongs to the workspace.\n- `rcs_not_found`: A device was removed by another request at the same time.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RcsNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_found"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no agent.",
                    "value": {
                      "error": "rcs_not_found",
                      "message": "No RCS agent with that id is set up on this workspace."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `rcs_field_locked`: The registration is in review (`awaiting_review` or `launch_requested`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "rcs_field_locked"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "rcs_field_locked",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "rcs_field_locked"
                  ],
                  "x-sendly-visibility": "preview"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `rcs_invalid_content`: `devices` is not a list, has more than 20 entries, or has a number that is not E.164. Checked before the agent is looked up.\n- `rcs_carrier_rejected`: Once the agent is in testing, the carrier network refused to invite or remove a device. `message` carries its reason. A new device it refused is not kept.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_invalid_content"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/RcsValidationIssue"
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errors"
                      ],
                      "title": "rcs_invalid_content, with the fields",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_invalid_content"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_carrier_rejected"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_carrier_rejected",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_carrier_rejected"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "`devices` is not a list, refused before the agent is looked up.",
                    "value": {
                      "error": "rcs_invalid_content",
                      "message": "Some registration fields need attention before this can continue.",
                      "errors": [
                        {
                          "path": "devices",
                          "message": "devices must be a list"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `rcs_carrier_unavailable`: The carrier network could not be reached, or failed, while inviting or removing a device. Try again in a few minutes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "rcs_carrier_unavailable"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "rcs_carrier_unavailable",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "rcs_carrier_unavailable"
                  ],
                  "x-sendly-visibility": "preview"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/brands": {
      "post": {
        "operationId": "createRcsBrand",
        "summary": "Create an RCS brand",
        "description": "Creates a brand draft. Nothing is sent for review or to the carrier network until an agent of the brand is submitted.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.brands",
          "method": "create"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The brand.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRcsBrandRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- The brand draft was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "brand": {
                      "$ref": "#/components/schemas/RcsBrand"
                    }
                  },
                  "required": [
                    "brand"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A US brand draft, built from createRcsBrand and toPublicRcsBrand: creating one in production would change the test account's registration.",
                    "value": {
                      "brand": {
                        "id": "00000000-0000-4000-8000-000000000001",
                        "reviewStatus": "draft",
                        "customerStage": "draft",
                        "displayName": "Example Coffee",
                        "legalName": "Example Coffee LLC",
                        "legalEntityType": "LIMITED_LIABILITY_COMPANY",
                        "organizationType": "PRIVATE_PROFIT",
                        "stockSymbol": null,
                        "websiteUrl": "https://www.example.com",
                        "ein": "12-3456789",
                        "address": {
                          "line1": "1 Main St",
                          "line2": null,
                          "city": "Chicago",
                          "state": "IL",
                          "postalCode": "60601",
                          "countryCode": "US"
                        },
                        "contact": {
                          "firstName": "Ada",
                          "lastName": "Lovelace",
                          "title": null,
                          "email": "user@example.com",
                          "phoneNumber": "+15555550101"
                        },
                        "reviewNote": null,
                        "rejectionReason": null,
                        "submittedForReviewAt": null,
                        "sentToCarrierAt": null,
                        "verifiedAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A body that is not valid JSON, answered by the body parser.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:write` permission for RCS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RcsNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `rcs_us_only`: `address.countryCode` is missing or not `US`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_us_only"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_us_only",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_us_only"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A brand outside the US, refused before anything is stored.",
                    "value": {
                      "error": "rcs_us_only",
                      "message": "RCS registration is available to US businesses for now."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/brands/{id}": {
      "patch": {
        "operationId": "updateRcsBrand",
        "summary": "Update an RCS brand",
        "description": "Changes a brand that has not been sent to the carrier network yet.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.brands",
          "method": "update"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The brand's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateRcsBrandRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- The brand, changed. A body with nothing to change returns it as is.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "brand": {
                      "$ref": "#/components/schemas/RcsBrand"
                    }
                  },
                  "required": [
                    "brand"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An empty patch on the test account's draft brand, which returns it unchanged.",
                    "value": {
                      "brand": {
                        "id": "00000000-0000-4000-8000-000000000001",
                        "reviewStatus": "draft",
                        "customerStage": "draft",
                        "displayName": "",
                        "legalName": "Sendly",
                        "legalEntityType": "LIMITED_LIABILITY_COMPANY",
                        "organizationType": "PRIVATE_PROFIT",
                        "stockSymbol": null,
                        "websiteUrl": "https://example.com/",
                        "ein": "asdsadasdsa",
                        "address": {
                          "line1": "asdsda",
                          "line2": null,
                          "city": "asdsada",
                          "state": "asfsafa",
                          "postalCode": "233WED",
                          "countryCode": "US"
                        },
                        "contact": {
                          "firstName": "Ada",
                          "lastName": "Lovelace",
                          "title": null,
                          "email": "user@example.com",
                          "phoneNumber": "+15555550100"
                        },
                        "reviewNote": null,
                        "rejectionReason": null,
                        "submittedForReviewAt": null,
                        "sentToCarrierAt": null,
                        "verifiedAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:write` permission for RCS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.\n- `rcs_not_found`: No brand with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RcsNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_found"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no brand.",
                    "value": {
                      "error": "rcs_not_found",
                      "message": "No RCS brand with that id is set up on this workspace."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `rcs_field_locked`: The registration is in review (`awaiting_review` or `launch_requested`), approved for the carrier network (`approved_for_carrier`), or already sent to it.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "rcs_field_locked"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "rcs_field_locked",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "rcs_field_locked"
                  ],
                  "x-sendly-visibility": "preview"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `rcs_us_only`: `address.countryCode` is sent and is not `US`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_us_only"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_us_only",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_us_only"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/capability": {
      "get": {
        "operationId": "checkRcsCapability",
        "summary": "Check whether a number can receive RCS",
        "description": "Asks the carrier network whether a number can receive RCS from one of the workspace's agents. Live keys only. An API key needs `rcs:read` or `sms:send`.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs",
          "method": "capability"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The number to check, in E.164 format. Everything but digits is dropped, and a 10-digit number without `+` is read as a US number."
            },
            "required": true,
            "name": "to",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "The agent to check as. Needed when the workspace has more than one."
            },
            "required": false,
            "name": "agentId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- RcsCapability: The carrier network answered.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RcsCapability"
                },
                "examples": {
                  "default": {
                    "summary": "A number that can receive RCS, built from the capability route: the check needs a live key and asks the carrier network.",
                    "value": {
                      "to": "+15555550100",
                      "agentId": "00000000-0000-4000-8000-000000000002",
                      "capable": true,
                      "features": [
                        "RICHCARD_STANDALONE",
                        "ACTION_DIAL",
                        "ACTION_OPEN_URL"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `rcs_invalid_content`: `to` is missing, or is not an E.164 number once read.\n- `rcs_agent_ambiguous`: `agentId` is missing and the workspace has more than one agent in testing or approved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_invalid_content"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_invalid_content: `to` missing or not E.164",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_invalid_content"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_agent_ambiguous"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_agent_ambiguous",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_agent_ambiguous"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key holds neither `rcs:read` nor `sms:send`. A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `rcs_requires_live_key`: A test key called it.\n- `rcs_agent_not_ready`: The agent is not in testing or approved, is not fully set up, its brand failed carrier verification, or (without `agentId`) every agent that could send is suspended. `agentStatus` is the agent's `status`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_requires_live_key"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_requires_live_key",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_requires_live_key"
                      ],
                      "x-sendly-visibility": "preview"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_agent_not_ready"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "agentStatus": {
                          "type": "string",
                          "description": "The agent's registration status."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "agentStatus"
                      ],
                      "title": "rcs_agent_not_ready",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_agent_not_ready"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked for a capability check, which needs a live key.",
                    "value": {
                      "error": "rcs_requires_live_key",
                      "message": "RCS capability checks require a live API key. Test keys cannot query RCS capability."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the workspace, or (without `agentId`) no agent is in testing or approved.\n- `rcs_not_found`: `agentId` names no agent of the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RcsNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "rcs_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "rcs_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "rcs_not_found"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `rcs_capability_check_failed`: The carrier network could not be asked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "rcs_capability_check_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "rcs_capability_check_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "rcs_capability_check_failed"
                  ],
                  "x-sendly-visibility": "preview"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/dossier": {
      "get": {
        "operationId": "getRcsDossier",
        "summary": "Get the business details on file",
        "description": "Returns the business details the workspace already gave for 10DLC or toll-free verification, shaped for creating a brand.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.dossier",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- RcsDossier: The details on file. `brand` is empty when there are none.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RcsDossier"
                },
                "examples": {
                  "default": {
                    "summary": "The business details on file, from the test account's toll-free verification.",
                    "value": {
                      "source": "verification",
                      "usEligible": true,
                      "verification": {
                        "verified": true,
                        "state": "verified",
                        "href": "/dashboard/verify/toll-free/status"
                      },
                      "brand": {
                        "legalName": "Sendly",
                        "ein": "asdsadasdsa",
                        "organizationType": "PRIVATE_PROFIT",
                        "websiteUrl": "https://example.com/",
                        "address": {
                          "line1": "asdsda",
                          "city": "asdsada",
                          "state": "asfsafa",
                          "postalCode": "233WED"
                        },
                        "contact": {
                          "firstName": "Ada",
                          "lastName": "Lovelace",
                          "email": "user@example.com",
                          "phoneNumber": "+15555550100"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:read` permission for RCS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RcsNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rcs/registration": {
      "get": {
        "operationId": "getRcsRegistration",
        "summary": "Get the RCS registration",
        "description": "Returns the workspace's registration at a glance: the newest agent, its brand and test devices, the stage, and the business verification. `agents` and `brands` list every agent and brand on the workspace.",
        "tags": [
          "RCS channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "rcs:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rcs.registration",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- RcsRegistration: The registration. `brand` and `agent` are `null` before they exist.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RcsRegistration"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since #254 the body also carries `brands` and `agents`, every brand and agent on the workspace. The production capture of 2026-10-03 predates that change. It was: The test account's registration: a draft brand and a draft agent.",
                    "value": {
                      "brand": {
                        "id": "00000000-0000-4000-8000-000000000001",
                        "reviewStatus": "draft",
                        "customerStage": "draft",
                        "displayName": "",
                        "legalName": "Sendly",
                        "legalEntityType": "LIMITED_LIABILITY_COMPANY",
                        "organizationType": "PRIVATE_PROFIT",
                        "stockSymbol": null,
                        "websiteUrl": "https://example.com/",
                        "ein": "asdsadasdsa",
                        "address": {
                          "line1": "asdsda",
                          "line2": null,
                          "city": "asdsada",
                          "state": "asfsafa",
                          "postalCode": "233WED",
                          "countryCode": "US"
                        },
                        "contact": {
                          "firstName": "Ada",
                          "lastName": "Lovelace",
                          "title": null,
                          "email": "user@example.com",
                          "phoneNumber": "+15555550100"
                        },
                        "reviewNote": null,
                        "rejectionReason": null,
                        "submittedForReviewAt": null,
                        "sentToCarrierAt": null,
                        "verifiedAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      },
                      "agent": {
                        "id": "00000000-0000-4000-8000-000000000002",
                        "brandId": "00000000-0000-4000-8000-000000000001",
                        "status": "draft",
                        "reviewStatus": "draft",
                        "customerStage": "draft",
                        "displayName": "",
                        "useCase": "TRANSACTIONAL",
                        "hostingRegion": null,
                        "basics": {
                          "email": null,
                          "heroUrl": "https://assets.sendly.live/brand-assets/rcs/00000000-0000-4000-8000-000000000003/hero-00000000-0000-4000-8000-000000000004.png",
                          "logoUrl": "https://assets.sendly.live/brand-assets/rcs/00000000-0000-4000-8000-000000000003/logo-00000000-0000-4000-8000-000000000005.png",
                          "website": null,
                          "brandColor": "#2563EB",
                          "description": "",
                          "phoneNumber": null,
                          "privacyPolicyUrl": "",
                          "termsAndConditionsUrl": "",
                          "displayName": "",
                          "useCase": "TRANSACTIONAL",
                          "hostingRegion": null
                        },
                        "campaign": {
                          "interactions": [],
                          "agentOverview": "",
                          "companyOverview": "",
                          "consentSettings": {
                            "doubleOptIn": false,
                            "callToAction": "",
                            "helpResponse": "",
                            "optInMessage": "",
                            "optInMethods": [],
                            "optOutResponse": "",
                            "callToActionUrl": null,
                            "doubleOptInMessage": null,
                            "callToActionMediaUrl": null
                          },
                          "messageExamples": [],
                          "additionalInformation": null
                        },
                        "testing": null,
                        "reviewNote": null,
                        "rejectionReason": null,
                        "testDevices": [],
                        "submittedForReviewAt": null,
                        "basicsSubmittedAt": null,
                        "launchSubmittedAt": null,
                        "liveAt": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      },
                      "devices": [],
                      "stage": "draft",
                      "brands": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "reviewStatus": "draft",
                          "customerStage": "draft",
                          "displayName": "",
                          "legalName": "Sendly",
                          "legalEntityType": "LIMITED_LIABILITY_COMPANY",
                          "organizationType": "PRIVATE_PROFIT",
                          "stockSymbol": null,
                          "websiteUrl": "https://example.com/",
                          "ein": "asdsadasdsa",
                          "address": {
                            "line1": "asdsda",
                            "line2": null,
                            "city": "asdsada",
                            "state": "asfsafa",
                            "postalCode": "233WED",
                            "countryCode": "US"
                          },
                          "contact": {
                            "firstName": "Ada",
                            "lastName": "Lovelace",
                            "title": null,
                            "email": "user@example.com",
                            "phoneNumber": "+15555550100"
                          },
                          "reviewNote": null,
                          "rejectionReason": null,
                          "submittedForReviewAt": null,
                          "sentToCarrierAt": null,
                          "verifiedAt": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z"
                        }
                      ],
                      "agents": [
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "brandId": "00000000-0000-4000-8000-000000000001",
                          "status": "draft",
                          "reviewStatus": "draft",
                          "customerStage": "draft",
                          "displayName": "",
                          "useCase": "TRANSACTIONAL",
                          "hostingRegion": null,
                          "basics": {
                            "email": null,
                            "heroUrl": "https://assets.sendly.live/brand-assets/rcs/00000000-0000-4000-8000-000000000003/hero-00000000-0000-4000-8000-000000000004.png",
                            "logoUrl": "https://assets.sendly.live/brand-assets/rcs/00000000-0000-4000-8000-000000000003/logo-00000000-0000-4000-8000-000000000005.png",
                            "website": null,
                            "brandColor": "#2563EB",
                            "description": "",
                            "phoneNumber": null,
                            "privacyPolicyUrl": "",
                            "termsAndConditionsUrl": "",
                            "displayName": "",
                            "useCase": "TRANSACTIONAL",
                            "hostingRegion": null
                          },
                          "campaign": {
                            "interactions": [],
                            "agentOverview": "",
                            "companyOverview": "",
                            "consentSettings": {
                              "doubleOptIn": false,
                              "callToAction": "",
                              "helpResponse": "",
                              "optInMessage": "",
                              "optInMethods": [],
                              "optOutResponse": "",
                              "callToActionUrl": null,
                              "doubleOptInMessage": null,
                              "callToActionMediaUrl": null
                            },
                            "messageExamples": [],
                            "additionalInformation": null
                          },
                          "testing": null,
                          "reviewNote": null,
                          "rejectionReason": null,
                          "testDevices": [],
                          "submittedForReviewAt": null,
                          "basicsSubmittedAt": null,
                          "launchSubmittedAt": null,
                          "liveAt": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z"
                        }
                      ],
                      "usEligible": true,
                      "verification": {
                        "verified": true,
                        "state": "verified",
                        "href": "/dashboard/verify/toll-free/status"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (rcs:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `verify:read` permission for RCS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `rcs_not_enabled`: RCS is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RcsNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `rcs_internal_error`: The account's RCS access could not be checked.\n- `rcs_internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/RcsInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rules": {
      "get": {
        "operationId": "listRules",
        "summary": "List auto-label rules",
        "description": "Lists every auto-label rule of the key's workspace, lowest `priority` first, enabled or not. A key with no workspace lists the account's rules that have no workspace.",
        "tags": [
          "Auto-label rules"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rules",
          "method": "list"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- AutoLabelRuleList: The rules, all on one page.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoLabelRuleList"
                },
                "examples": {
                  "default": {
                    "summary": "The test key's rules: the one the capture created.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "userId": "00000000-0000-4000-8000-000000000002",
                          "organizationId": null,
                          "name": "Contract capture rule",
                          "conditions": {
                            "intent": [
                              "contract_capture_never_matches"
                            ],
                            "intentConfidenceMin": 0.99
                          },
                          "actions": {
                            "addLabels": [],
                            "closeConversation": false
                          },
                          "enabled": true,
                          "priority": 900,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The rules could not be read. `message` is the thrown error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createRule",
        "summary": "Create an auto-label rule",
        "description": "Creates an enabled rule in the key's workspace. Rules run only on inbound messages the classifier labels, which happens only on accounts with message classification turned on. Each server keeps the enabled rules for up to a minute, so a new rule can take that long to run everywhere.",
        "tags": [
          "Auto-label rules"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rules",
          "method": "create"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The rule to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAutoLabelRuleRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- AutoLabelRule: The rule was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoLabelRule"
                },
                "examples": {
                  "default": {
                    "summary": "A rule whose intent the classifier never gives, so it never runs.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "userId": "00000000-0000-4000-8000-000000000002",
                      "organizationId": null,
                      "name": "Contract capture rule",
                      "conditions": {
                        "intent": [
                          "contract_capture_never_matches"
                        ],
                        "intentConfidenceMin": 0.99
                      },
                      "actions": {
                        "addLabels": [],
                        "closeConversation": false
                      },
                      "enabled": true,
                      "priority": 900,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `name`, `conditions` or `actions` is missing, or is an empty string, `0`, `false` or `null`, or a field does not fit its type: `name` over 200 characters, a condition or action field that is not listed, a confidence outside 0 to 1, or a `priority` that is not an integer. `message` names the first field that does not fit.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "`conditions` and `actions` are missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "name, conditions, and actions are required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The rule could not be stored, such as a `priority` past the 32-bit integer range. `message` is the database's own error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A `priority` that is not an integer, refused by the database.",
                    "value": {
                      "error": "internal_error",
                      "message": "invalid input syntax for type integer: \"high\""
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rules/{id}": {
      "patch": {
        "operationId": "updateRule",
        "summary": "Update an auto-label rule",
        "description": "Changes a rule of the key's workspace, and returns it. Each server keeps the enabled rules for up to a minute, so the old version can keep running that long.",
        "tags": [
          "Auto-label rules"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rules",
          "method": "update"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The rule's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAutoLabelRuleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- AutoLabelRule: The rule, as changed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoLabelRule"
                },
                "examples": {
                  "default": {
                    "summary": "The capture's rule, disabled and moved to priority 901.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "userId": "00000000-0000-4000-8000-000000000002",
                      "organizationId": null,
                      "name": "Contract capture rule",
                      "conditions": {
                        "intent": [
                          "contract_capture_never_matches"
                        ],
                        "intentConfidenceMin": 0.99
                      },
                      "actions": {
                        "addLabels": [],
                        "closeConversation": false
                      },
                      "enabled": false,
                      "priority": 901,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "null-enabled": {
                    "summary": "`enabled: null` is stored as is, and the rule answers `enabled: null`.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "userId": "00000000-0000-4000-8000-000000000002",
                      "organizationId": null,
                      "name": "Contract capture rule",
                      "conditions": {
                        "intent": [
                          "contract_capture_never_matches"
                        ],
                        "intentConfidenceMin": 0.99
                      },
                      "actions": {
                        "addLabels": [],
                        "closeConversation": false
                      },
                      "enabled": null,
                      "priority": 901,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "unchecked-values": {
                    "summary": "`conditions` and `actions` that are not objects are stored and returned as sent. The rule is no longer enabled, so it never runs.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "userId": "00000000-0000-4000-8000-000000000002",
                      "organizationId": null,
                      "name": "Contract capture rule",
                      "conditions": "contract capture, not an object",
                      "actions": [],
                      "enabled": null,
                      "priority": 901,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: A field does not fit its type: an empty or `null` `name`, a `name` over 200 characters, a condition or action field that is not listed, a confidence outside 0 to 1, an `enabled` that is not a boolean, or a `priority` that is not an integer. `message` names the first field that does not fit.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No rule with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no rule.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The change could not be stored, such as a `priority` past the 32-bit integer range. `message` is the database's own error text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A `priority` that is not an integer, refused by the database.",
                    "value": {
                      "error": "internal_error",
                      "message": "invalid input syntax for type integer: \"high\""
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteRule",
        "summary": "Delete an auto-label rule",
        "description": "Deletes a rule of the key's workspace. Labels it already added stay on their conversations. Each server keeps the enabled rules for up to a minute, so the rule can keep running that long.",
        "tags": [
          "Auto-label rules"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "rules",
          "method": "delete"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The rule's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- DeleteAutoLabelRuleResult: The rule was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteAutoLabelRuleResult"
                },
                "examples": {
                  "default": {
                    "summary": "The capture's rule, deleted.",
                    "value": {
                      "success": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No rule with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                },
                "examples": {
                  "already-deleted": {
                    "summary": "The rule the previous scenario deleted.",
                    "value": {
                      "error": "not_found"
                    }
                  },
                  "default": {
                    "summary": "An id that matches no rule.",
                    "value": {
                      "error": "not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The rule could not be deleted. `message` is the thrown error's own text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/short_codes": {
      "get": {
        "operationId": "listShortCodes",
        "summary": "List short codes",
        "description": "Lists every short code application of the workspace, newest first, with its code once Sendly assigns one. Behind the `short_codes` flag.",
        "tags": [
          "Short codes"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "short_codes:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "shortCodes",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- ShortCodeList: The workspace's short codes and applications, each with its billing.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodeList"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #220 (4b5955ec) each code carries `billing`, built here from shortCodeListBilling for a draft with no charges and billing off. The production capture of 2026-10-03 predates that change. It was: The mock workspace's short code applications.",
                    "value": {
                      "shortCodes": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "shortCode": null,
                          "countryCode": "US",
                          "status": "requested",
                          "reviewStatus": "draft",
                          "useCase": "Sendly sends account security messages to its own registered users to help protect their accounts. These messages include two-factor authentication codes, alerts about new or suspicious logins, and confirmations of account activity such as password changes. Messages are sent only when triggered by a security event, such as a login attempt or a code request, so volume varies per user rather than following a fixed schedule. Sendly expects to send approximately 10,000 messages per month across all users.",
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "billing": {
                            "setupFee": {
                              "status": "unpaid",
                              "amountCents": 99900
                            },
                            "lease": {
                              "monthlyCents": 115000,
                              "minimumTermMonths": 3,
                              "state": "not_started",
                              "billingEnabled": false,
                              "startedAt": null,
                              "nextChargeAt": null,
                              "paidThrough": null,
                              "termEndsAt": null,
                              "endsAt": null,
                              "cancelRequestedAt": null,
                              "pastDue": null,
                              "dueMonths": 0,
                              "dueCents": 0
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (short_codes:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `settings:read` permission for short codes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `short_codes_not_enabled`: Short codes is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodesNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `short_code_internal_error`: The account's Short codes access could not be checked.\n- `short_code_internal_error`: The short codes could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ShortCodeInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/short_codes/application": {
      "get": {
        "operationId": "getShortCodeApplication",
        "summary": "Get the short code application",
        "description": "Returns the workspace's short code application: the open one, or with none open the newest finished one, or the empty shape when there is none. With it come the suggestions from the workspace's business details, the carrier forms, the quoted lease, the business verification and each carrier's certification.",
        "tags": [
          "Short codes"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "short_codes:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "shortCodes.application",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- ShortCodeApplicationView: The application.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodeApplicationView"
                },
                "examples": {
                  "default": {
                    "summary": "Built from toPublicApplication and applicationPayload in server/short-codes/routes.ts: an editable draft, with suggestions from a 10DLC brand. Not captured, because the body carries the workspace's business details. Since main's #218, #219 and #220 the view carries `billing`, and `quote` the fee and lease in cents, built here from shortCodeBillingSummary and shortCodeQuoteBilling with the lease not started and billing off.",
                    "value": {
                      "application": {
                        "activatedAt": null,
                        "brandContactEmail": "user@example.com",
                        "brandContactName": "Ada Lovelace",
                        "brandContactPhone": null,
                        "brandRegistrationStatus": "not_started",
                        "campaignKeyword": null,
                        "codeType": "random",
                        "contentProviderContactEmail": null,
                        "contentProviderContactName": null,
                        "contentProviderContactPhone": null,
                        "contentProviderEin": null,
                        "contentProviderLegalName": null,
                        "contentProviderRegistrationStatus": "not_started",
                        "contentProviderSameAsBrand": true,
                        "countryCode": "US",
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "expectedDailyVolume": null,
                        "expectedMonthlyVolume": "50000",
                        "filedAt": null,
                        "helpResponse": "Example Shop Order Alerts: Help at help@example.com or +15555550123. Msg&data rates may apply. 4 messages per month. Text STOP to cancel.",
                        "id": "00000000-0000-4000-8000-000000000001",
                        "losingProvider": null,
                        "messageFrequency": "4 messages per month",
                        "optInConfirmation": null,
                        "optInFlow": "Customers tick an unchecked box at checkout that says they agree to receive order texts.",
                        "orderType": "new",
                        "privacyPolicyUrl": "https://shop.example.com/privacy",
                        "registryRevettingDueAt": null,
                        "requestedDigits": null,
                        "reviewNote": null,
                        "reviewStatus": "draft",
                        "reviewedAt": null,
                        "sampleMessages": [
                          "Example Shop: your order has shipped. Reply STOP to opt out."
                        ],
                        "shortCode": null,
                        "status": "requested",
                        "stopConfirmation": "You are unsubscribed from Example Shop Order Alerts. No more messages will be sent. Reply HELP for help.",
                        "submittedAt": null,
                        "termsUrl": "https://shop.example.com/sms-terms",
                        "updatedAt": "2026-01-01T00:00:00.000Z",
                        "useCase": "Order and delivery updates for Example Shop customers."
                      },
                      "canStartNewApplication": false,
                      "carriers": {
                        "approved": 0,
                        "byCarrier": [
                          {
                            "carrier": "ATT",
                            "label": "AT&T",
                            "status": "not_submitted",
                            "updatedAt": null
                          },
                          {
                            "carrier": "TMOBILE",
                            "label": "T-Mobile",
                            "status": "not_submitted",
                            "updatedAt": null
                          },
                          {
                            "carrier": "VERIZON",
                            "label": "Verizon",
                            "status": "not_submitted",
                            "updatedAt": null
                          },
                          {
                            "carrier": "US_CELLULAR",
                            "label": "US Cellular",
                            "status": "not_submitted",
                            "updatedAt": null
                          }
                        ],
                        "overall": "not_submitted",
                        "total": 4
                      },
                      "documents": [],
                      "editable": true,
                      "enabled": true,
                      "generatedDefaults": null,
                      "lockMessage": null,
                      "missingDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration"
                      ],
                      "prefill": {
                        "address": {
                          "city": "Springfield",
                          "countryCode": "US",
                          "line1": "1 Example Street",
                          "postalCode": "62701",
                          "state": "IL"
                        },
                        "contact": {
                          "email": "user@example.com",
                          "name": "Ada Lovelace",
                          "phone": "+15555550123"
                        },
                        "ein": "12-3456789",
                        "legalName": "Example Shop LLC",
                        "privacyPolicyUrl": "https://shop.example.com/privacy",
                        "source": "tendlc",
                        "termsUrl": "https://shop.example.com/sms-terms",
                        "usesHostedLegalPages": false,
                        "websiteUrl": "https://shop.example.com"
                      },
                      "quote": {
                        "autoBilled": false,
                        "codeType": "random",
                        "currency": "USD",
                        "monthlyUsd": 1150,
                        "setupUsd": 999,
                        "setupCents": 99900,
                        "monthlyCents": 115000,
                        "minimumTermMonths": 3,
                        "setupChargedAt": "submit",
                        "leaseStartsAt": "go_live"
                      },
                      "billing": {
                        "setupFee": {
                          "amountCents": 99900,
                          "status": "unpaid",
                          "chargedAt": "submit",
                          "paidAt": null,
                          "refundedCents": 0,
                          "refundedAt": null
                        },
                        "lease": {
                          "monthlyCents": 115000,
                          "minimumTermMonths": 3,
                          "startsAt": "go_live",
                          "state": "not_started",
                          "billingEnabled": false,
                          "startedAt": null,
                          "nextChargeAt": null,
                          "paidThrough": null,
                          "termEndsAt": null,
                          "endsAt": null,
                          "cancelRequestedAt": null,
                          "pastDue": null,
                          "dueMonths": 0,
                          "dueCents": 0
                        },
                        "terms": {
                          "version": "2026-10-06",
                          "acceptedVersion": null,
                          "acceptedAt": null
                        },
                        "refundPolicy": "full_refund_before_filing",
                        "exempt": null,
                        "charges": []
                      },
                      "requiredDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration"
                      ],
                      "verification": {
                        "href": "/10dlc/status",
                        "state": "verified",
                        "verified": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (short_codes:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `settings:read` permission for short codes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `short_codes_not_enabled`: Short codes is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodesNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `short_code_internal_error`: The account's Short codes access could not be checked.\n- `short_code_internal_error`: Reading or saving the application failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ShortCodeInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "saveShortCodeApplication",
        "summary": "Save the short code application",
        "description": "Saves answers on the workspace's application, creating it on the first save, even an empty one. After a rejected or cancelled application, the save starts a new one. It never changes the status or the review status, and never submits.",
        "tags": [
          "Short codes"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "short_codes:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "shortCodes.application",
          "method": "update"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The answers to save.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShortCodeApplicationInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ShortCodeApplicationSaved: The application as saved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodeApplicationSaved"
                },
                "examples": {
                  "default": {
                    "summary": "Built from saveShortCodeApplication in server/short-codes/routes.ts: a save that also sent a server-owned field, named back in ignoredFields. Not captured, because a save changes the workspace's application. Since main's #218, #219 and #220 the view carries `billing`, and `quote` the fee and lease in cents, built here from shortCodeBillingSummary and shortCodeQuoteBilling with the lease not started and billing off.",
                    "value": {
                      "application": {
                        "activatedAt": null,
                        "brandContactEmail": "user@example.com",
                        "brandContactName": "Ada Lovelace",
                        "brandContactPhone": null,
                        "brandRegistrationStatus": "not_started",
                        "campaignKeyword": null,
                        "codeType": "random",
                        "contentProviderContactEmail": null,
                        "contentProviderContactName": null,
                        "contentProviderContactPhone": null,
                        "contentProviderEin": null,
                        "contentProviderLegalName": null,
                        "contentProviderRegistrationStatus": "not_started",
                        "contentProviderSameAsBrand": true,
                        "countryCode": "US",
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "expectedDailyVolume": null,
                        "expectedMonthlyVolume": "50000",
                        "filedAt": null,
                        "helpResponse": "Example Shop Order Alerts: Help at help@example.com or +15555550123. Msg&data rates may apply. 4 messages per month. Text STOP to cancel.",
                        "id": "00000000-0000-4000-8000-000000000001",
                        "losingProvider": null,
                        "messageFrequency": "4 messages per month",
                        "optInConfirmation": null,
                        "optInFlow": "Customers tick an unchecked box at checkout that says they agree to receive order texts.",
                        "orderType": "new",
                        "privacyPolicyUrl": "https://shop.example.com/privacy",
                        "registryRevettingDueAt": null,
                        "requestedDigits": null,
                        "reviewNote": null,
                        "reviewStatus": "draft",
                        "reviewedAt": null,
                        "sampleMessages": [
                          "Example Shop: your order has shipped. Reply STOP to opt out."
                        ],
                        "shortCode": null,
                        "status": "requested",
                        "stopConfirmation": "You are unsubscribed from Example Shop Order Alerts. No more messages will be sent. Reply HELP for help.",
                        "submittedAt": null,
                        "termsUrl": "https://shop.example.com/sms-terms",
                        "updatedAt": "2026-01-01T00:00:00.000Z",
                        "useCase": "Order and delivery updates for Example Shop customers."
                      },
                      "canStartNewApplication": false,
                      "carriers": {
                        "approved": 0,
                        "byCarrier": [
                          {
                            "carrier": "ATT",
                            "label": "AT&T",
                            "status": "not_submitted",
                            "updatedAt": null
                          },
                          {
                            "carrier": "TMOBILE",
                            "label": "T-Mobile",
                            "status": "not_submitted",
                            "updatedAt": null
                          },
                          {
                            "carrier": "VERIZON",
                            "label": "Verizon",
                            "status": "not_submitted",
                            "updatedAt": null
                          },
                          {
                            "carrier": "US_CELLULAR",
                            "label": "US Cellular",
                            "status": "not_submitted",
                            "updatedAt": null
                          }
                        ],
                        "overall": "not_submitted",
                        "total": 4
                      },
                      "documents": [],
                      "editable": true,
                      "enabled": true,
                      "generatedDefaults": null,
                      "ignoredFields": [
                        "status"
                      ],
                      "lockMessage": null,
                      "missingDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration"
                      ],
                      "prefill": {
                        "address": {
                          "city": "Springfield",
                          "countryCode": "US",
                          "line1": "1 Example Street",
                          "postalCode": "62701",
                          "state": "IL"
                        },
                        "contact": {
                          "email": "user@example.com",
                          "name": "Ada Lovelace",
                          "phone": "+15555550123"
                        },
                        "ein": "12-3456789",
                        "legalName": "Example Shop LLC",
                        "privacyPolicyUrl": "https://shop.example.com/privacy",
                        "source": "tendlc",
                        "termsUrl": "https://shop.example.com/sms-terms",
                        "usesHostedLegalPages": false,
                        "websiteUrl": "https://shop.example.com"
                      },
                      "quote": {
                        "autoBilled": false,
                        "codeType": "random",
                        "currency": "USD",
                        "monthlyUsd": 1150,
                        "setupUsd": 999,
                        "setupCents": 99900,
                        "monthlyCents": 115000,
                        "minimumTermMonths": 3,
                        "setupChargedAt": "submit",
                        "leaseStartsAt": "go_live"
                      },
                      "billing": {
                        "setupFee": {
                          "amountCents": 99900,
                          "status": "unpaid",
                          "chargedAt": "submit",
                          "paidAt": null,
                          "refundedCents": 0,
                          "refundedAt": null
                        },
                        "lease": {
                          "monthlyCents": 115000,
                          "minimumTermMonths": 3,
                          "startsAt": "go_live",
                          "state": "not_started",
                          "billingEnabled": false,
                          "startedAt": null,
                          "nextChargeAt": null,
                          "paidThrough": null,
                          "termEndsAt": null,
                          "endsAt": null,
                          "cancelRequestedAt": null,
                          "pastDue": null,
                          "dueMonths": 0,
                          "dueCents": 0
                        },
                        "terms": {
                          "version": "2026-10-06",
                          "acceptedVersion": null,
                          "acceptedAt": null
                        },
                        "refundPolicy": "full_refund_before_filing",
                        "exempt": null,
                        "charges": []
                      },
                      "requiredDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration"
                      ],
                      "verification": {
                        "href": "/10dlc/status",
                        "state": "verified",
                        "verified": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (short_codes:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `settings:write` permission for short codes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `short_codes_not_enabled`: Short codes is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodesNotEnabledError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `short_code_locked`, `short_code_conflict`: The application is with Sendly or the carriers and cannot be edited (`short_code_locked`, with `message` saying why), or another save changed it first (`short_code_conflict`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "short_code_locked",
                        "short_code_conflict"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "Short code application cannot change",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "short_code_locked",
                    "short_code_conflict"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `short_code_invalid_application`: `orderType` or `codeType` is not a known value.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_invalid_application"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ShortCodeIssue"
                          },
                          "description": "The `orderType` and `codeType` issues found."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errors"
                      ],
                      "title": "short_code_invalid_application: order or code type",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_invalid_application"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An order type the carriers do not have. Nothing is saved.",
                    "value": {
                      "error": "short_code_invalid_application",
                      "message": "Some details need attention before this application can be submitted.",
                      "errors": [
                        {
                          "path": "orderType",
                          "message": "Order type must be \"new\" or \"migration\"."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `short_code_internal_error`: The account's Short codes access could not be checked.\n- `short_code_internal_error`: Reading or saving the application failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ShortCodeInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/short_codes/application/preflight": {
      "post": {
        "operationId": "preflightShortCodeApplication",
        "summary": "Check the short code application",
        "description": "Checks the saved application, with the body's unsaved answers laid over it, against the rules a submit enforces, and reports every issue at once. Saves nothing. The carrier forms are listed but not checked: they are signed after review.",
        "tags": [
          "Short codes"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "short_codes:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "shortCodes.application",
          "method": "check"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "requestBody": {
          "description": "Unsaved answers to check with the saved ones. Can be empty.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShortCodeApplicationInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ShortCodePreflight: The result: `ok` is `false` when there is any issue.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodePreflight"
                },
                "examples": {
                  "ignored-fields": {
                    "summary": "Fields Sendly owns are named back in ignoredFields, and the order type is matched ignoring case. Nothing is saved.",
                    "value": {
                      "ok": false,
                      "issues": [
                        {
                          "path": "optInFlow",
                          "message": "Describe how subscribers opt in to these messages."
                        },
                        {
                          "path": "sampleMessages",
                          "message": "Add at least one real example of a message you will send."
                        },
                        {
                          "path": "expectedMonthlyVolume",
                          "message": "Estimate how many messages you will send in a month."
                        },
                        {
                          "path": "messageFrequency",
                          "message": "Message frequency is required."
                        },
                        {
                          "path": "helpResponse",
                          "message": "A HELP response is required."
                        },
                        {
                          "path": "stopConfirmation",
                          "message": "A STOP response is required."
                        },
                        {
                          "path": "useCase",
                          "message": "This is still the suggested use case. Edit it to describe your own programme before submitting."
                        }
                      ],
                      "requiredDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration"
                      ],
                      "missingDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration"
                      ],
                      "documents": [],
                      "ignoredFields": [
                        "status",
                        "short_code"
                      ]
                    }
                  },
                  "default": {
                    "summary": "A dry run of the saved application, with nothing unsaved.",
                    "value": {
                      "ok": false,
                      "issues": [
                        {
                          "path": "optInFlow",
                          "message": "Describe how subscribers opt in to these messages."
                        },
                        {
                          "path": "sampleMessages",
                          "message": "Add at least one real example of a message you will send."
                        },
                        {
                          "path": "expectedMonthlyVolume",
                          "message": "Estimate how many messages you will send in a month."
                        },
                        {
                          "path": "losingProvider",
                          "message": "Name the provider the code is moving from — they have to release it to our registry account."
                        },
                        {
                          "path": "requestedDigits",
                          "message": "Give the short code being migrated."
                        },
                        {
                          "path": "messageFrequency",
                          "message": "Message frequency is required."
                        },
                        {
                          "path": "helpResponse",
                          "message": "A HELP response is required."
                        },
                        {
                          "path": "stopConfirmation",
                          "message": "A STOP response is required."
                        },
                        {
                          "path": "useCase",
                          "message": "This is still the suggested use case. Edit it to describe your own programme before submitting."
                        }
                      ],
                      "requiredDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration",
                        "migration_letter",
                        "loa"
                      ],
                      "missingDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration",
                        "migration_letter",
                        "loa"
                      ],
                      "documents": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (short_codes:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `settings:read` permission for short codes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `short_codes_not_enabled`: Short codes is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodesNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `short_code_invalid_application`: `orderType` or `codeType` is not a known value.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "short_code_invalid_application"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ShortCodeIssue"
                      },
                      "description": "The `orderType` and `codeType` issues found."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "errors"
                  ],
                  "title": "short_code_invalid_application: order or code type",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "short_code_invalid_application"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A code type the carriers do not have.",
                    "value": {
                      "error": "short_code_invalid_application",
                      "message": "Some details need attention before this application can be submitted.",
                      "errors": [
                        {
                          "path": "codeType",
                          "message": "Code type must be \"random\" or \"vanity\"."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `short_code_internal_error`: The account's Short codes access could not be checked.\n- `short_code_internal_error`: Reading or saving the application failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ShortCodeInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/short_codes/application/submit": {
      "post": {
        "operationId": "submitShortCodeApplication",
        "summary": "Submit the short code application",
        "description": "Saves the body's answers, then charges the one-time setup fee to the workspace's card and submits the application to Sendly for review. It needs `acceptTerms: true`, accepting the fee, the monthly lease from go-live and the minimum term. A declined card, a missing card or a bank's confirmation step keeps the application a draft and answers 402 with the next step. Submitting again while it is in review answers 200 with `alreadySubmitted`, and never charges twice.",
        "tags": [
          "Short codes"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "short_codes:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "shortCodes.application",
          "method": "submit"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "Final answers, checked and saved before the submit, and `acceptTerms`.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitShortCodeApplicationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ShortCodeApplicationSubmitted: The application is with Sendly for review, now or already.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodeApplicationSubmitted"
                },
                "examples": {
                  "default": {
                    "summary": "Built from submitShortCodeApplication in server/short-codes/routes.ts: a complete application, now with Sendly for review. Not captured, because a submit files a real application. Since main's #218, #219 and #220 the view carries `billing`, and `quote` the fee and lease in cents, built here from shortCodeBillingSummary and shortCodeQuoteBilling with the lease not started and billing off. The submit charged the setup fee: `payment` says so.",
                    "value": {
                      "alreadySubmitted": false,
                      "application": {
                        "activatedAt": null,
                        "brandContactEmail": "user@example.com",
                        "brandContactName": "Ada Lovelace",
                        "brandContactPhone": null,
                        "brandRegistrationStatus": "not_started",
                        "campaignKeyword": null,
                        "codeType": "random",
                        "contentProviderContactEmail": null,
                        "contentProviderContactName": null,
                        "contentProviderContactPhone": null,
                        "contentProviderEin": null,
                        "contentProviderLegalName": null,
                        "contentProviderRegistrationStatus": "not_started",
                        "contentProviderSameAsBrand": true,
                        "countryCode": "US",
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "expectedDailyVolume": null,
                        "expectedMonthlyVolume": "50000",
                        "filedAt": null,
                        "helpResponse": "Example Shop Order Alerts: Help at help@example.com or +15555550123. Msg&data rates may apply. 4 messages per month. Text STOP to cancel.",
                        "id": "00000000-0000-4000-8000-000000000001",
                        "losingProvider": null,
                        "messageFrequency": "4 messages per month",
                        "optInConfirmation": null,
                        "optInFlow": "Customers tick an unchecked box at checkout that says they agree to receive order texts.",
                        "orderType": "new",
                        "privacyPolicyUrl": "https://shop.example.com/privacy",
                        "registryRevettingDueAt": null,
                        "requestedDigits": null,
                        "reviewNote": null,
                        "reviewStatus": "awaiting_review",
                        "reviewedAt": null,
                        "sampleMessages": [
                          "Example Shop: your order has shipped. Reply STOP to opt out."
                        ],
                        "shortCode": null,
                        "status": "requested",
                        "stopConfirmation": "You are unsubscribed from Example Shop Order Alerts. No more messages will be sent. Reply HELP for help.",
                        "submittedAt": "2026-01-01T00:00:00.000Z",
                        "termsUrl": "https://shop.example.com/sms-terms",
                        "updatedAt": "2026-01-01T00:00:00.000Z",
                        "useCase": "Order and delivery updates for Example Shop customers."
                      },
                      "canStartNewApplication": false,
                      "carriers": {
                        "approved": 0,
                        "byCarrier": [
                          {
                            "carrier": "ATT",
                            "label": "AT&T",
                            "status": "not_submitted",
                            "updatedAt": null
                          },
                          {
                            "carrier": "TMOBILE",
                            "label": "T-Mobile",
                            "status": "not_submitted",
                            "updatedAt": null
                          },
                          {
                            "carrier": "VERIZON",
                            "label": "Verizon",
                            "status": "not_submitted",
                            "updatedAt": null
                          },
                          {
                            "carrier": "US_CELLULAR",
                            "label": "US Cellular",
                            "status": "not_submitted",
                            "updatedAt": null
                          }
                        ],
                        "overall": "not_submitted",
                        "total": 4
                      },
                      "documents": [],
                      "editable": false,
                      "enabled": true,
                      "generatedDefaults": null,
                      "lockMessage": "This application is with us for review; we will email you if changes are needed.",
                      "missingDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration"
                      ],
                      "notified": true,
                      "prefill": {
                        "address": {
                          "city": "Springfield",
                          "countryCode": "US",
                          "line1": "1 Example Street",
                          "postalCode": "62701",
                          "state": "IL"
                        },
                        "contact": {
                          "email": "user@example.com",
                          "name": "Ada Lovelace",
                          "phone": "+15555550123"
                        },
                        "ein": "12-3456789",
                        "legalName": "Example Shop LLC",
                        "privacyPolicyUrl": "https://shop.example.com/privacy",
                        "source": "tendlc",
                        "termsUrl": "https://shop.example.com/sms-terms",
                        "usesHostedLegalPages": false,
                        "websiteUrl": "https://shop.example.com"
                      },
                      "quote": {
                        "autoBilled": false,
                        "codeType": "random",
                        "currency": "USD",
                        "monthlyUsd": 1150,
                        "setupUsd": 999,
                        "setupCents": 99900,
                        "monthlyCents": 115000,
                        "minimumTermMonths": 3,
                        "setupChargedAt": "submit",
                        "leaseStartsAt": "go_live"
                      },
                      "billing": {
                        "setupFee": {
                          "amountCents": 99900,
                          "status": "paid",
                          "chargedAt": "submit",
                          "paidAt": "2026-01-01T00:00:00.000Z",
                          "refundedCents": 0,
                          "refundedAt": null
                        },
                        "lease": {
                          "monthlyCents": 115000,
                          "minimumTermMonths": 3,
                          "startsAt": "go_live",
                          "state": "not_started",
                          "billingEnabled": false,
                          "startedAt": null,
                          "nextChargeAt": null,
                          "paidThrough": null,
                          "termEndsAt": null,
                          "endsAt": null,
                          "cancelRequestedAt": null,
                          "pastDue": null,
                          "dueMonths": 0,
                          "dueCents": 0
                        },
                        "terms": {
                          "version": "2026-10-06",
                          "acceptedVersion": "2026-10-06",
                          "acceptedAt": "2026-01-01T00:00:00.000Z"
                        },
                        "refundPolicy": "full_refund_before_filing",
                        "exempt": null,
                        "charges": [
                          {
                            "id": "00000000-0000-4000-8000-000000000201",
                            "kind": "setup",
                            "amountCents": 99900,
                            "status": "paid",
                            "paidAt": "2026-01-01T00:00:00.000Z",
                            "refundedCents": 0,
                            "refundedAt": null,
                            "periodStart": null,
                            "periodEnd": null,
                            "createdAt": "2026-01-01T00:00:00.000Z"
                          }
                        ]
                      },
                      "requiredDocuments": [
                        "order_brief",
                        "brand_registration",
                        "content_provider_registration"
                      ],
                      "submitted": true,
                      "verification": {
                        "href": "/10dlc/status",
                        "state": "verified",
                        "verified": true
                      },
                      "payment": {
                        "status": "paid",
                        "charged": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `payment_method_required`, `payment_failed`, `payment_requires_authentication`: The setup fee was not taken: no card on the workspace (`payment_method_required`), a declined card (`payment_failed`), or a bank that wants the payment confirmed (`payment_requires_authentication`, with `checkoutUrl` when the payment page opened). The application stays a draft.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "payment_method_required",
                        "payment_failed",
                        "payment_requires_authentication"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "nextStep": {
                      "type": "string",
                      "description": "What to do next. Known values: `add_payment_method`, `update_payment_method`, `complete_payment`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "add_payment_method",
                        "update_payment_method",
                        "complete_payment"
                      ]
                    },
                    "feature": {
                      "type": "string",
                      "enum": [
                        "short_code_setup"
                      ]
                    },
                    "amountCents": {
                      "type": "integer",
                      "description": "The setup fee, in US cents."
                    },
                    "actionUrl": {
                      "type": "string",
                      "enum": [
                        "/billing"
                      ],
                      "description": "The dashboard page to pay from."
                    },
                    "checkoutUrl": {
                      "type": "string",
                      "description": "The secure payment page to confirm the payment on, when it opened."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "nextStep",
                    "feature",
                    "amountCents",
                    "actionUrl"
                  ],
                  "title": "Short code setup fee not taken",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "payment_method_required",
                    "payment_failed",
                    "payment_requires_authentication"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (short_codes:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `settings:write` permission for short codes.\n- `verification_required`: The workspace's business is not verified. The body's answers were saved anyway.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "verification_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "verification_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "verification_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `short_codes_not_enabled`: Short codes is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodesNotEnabledError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `short_code_locked`, `short_code_conflict`: The application is past review, filed or live, or was rejected or cancelled while the fee was being taken, which refunds it (`short_code_locked`), or another save changed it first (`short_code_conflict`).\n- `short_code_payment_in_progress`, `short_code_refund_pending`: A payment of the setup fee is already in progress (`short_code_payment_in_progress`), or a refund of it is still going through (`short_code_refund_pending`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_locked",
                            "short_code_conflict"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "Short code application cannot change",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_locked",
                        "short_code_conflict"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_payment_in_progress",
                            "short_code_refund_pending"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "Short code setup fee busy",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_payment_in_progress",
                        "short_code_refund_pending"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `short_code_invalid_application`, `short_code_ai_draft_unedited`: The application is not complete or not compliant, or `acceptTerms` is not `true` (path `acceptTerms`), with every issue in `errors`. Nothing was saved. `short_code_ai_draft_unedited` when the only issues are wording Sendly suggested and nobody edited.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_invalid_application",
                            "short_code_ai_draft_unedited"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ShortCodeIssue"
                          },
                          "description": "Every issue found, all at once."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "errors"
                      ],
                      "title": "Short code application not valid",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_invalid_application",
                        "short_code_ai_draft_unedited"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A blank use case, refused with every issue before anything is saved.",
                    "value": {
                      "error": "short_code_invalid_application",
                      "message": "Some details need attention before this application can be submitted.",
                      "errors": [
                        {
                          "path": "useCase",
                          "message": "Describe what the short code will be used for."
                        },
                        {
                          "path": "optInFlow",
                          "message": "Describe how subscribers opt in to these messages."
                        },
                        {
                          "path": "sampleMessages",
                          "message": "Add at least one real example of a message you will send."
                        },
                        {
                          "path": "expectedMonthlyVolume",
                          "message": "Estimate how many messages you will send in a month."
                        },
                        {
                          "path": "losingProvider",
                          "message": "Name the provider the code is moving from — they have to release it to our registry account."
                        },
                        {
                          "path": "requestedDigits",
                          "message": "Give the short code being migrated."
                        },
                        {
                          "path": "messageFrequency",
                          "message": "Message frequency is required."
                        },
                        {
                          "path": "helpResponse",
                          "message": "A HELP response is required."
                        },
                        {
                          "path": "stopConfirmation",
                          "message": "A STOP response is required."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `short_code_internal_error`: The account's Short codes access could not be checked.\n- `short_code_internal_error`: Reading or saving the application failed.\n- `short_code_payment_not_recorded`: The card was charged but the payment could not be recorded, so it was refunded at once. The application stays a draft.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ShortCodeInternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_payment_not_recorded"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "short_code_payment_not_recorded",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_payment_not_recorded"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `short_code_payment_unconfirmed`: The card processor could not confirm the payment. The application stays a draft; submit again in a few minutes, and a payment that went through is used, not charged again.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "short_code_payment_unconfirmed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "short_code_payment_unconfirmed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "short_code_payment_unconfirmed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/short_codes/requests": {
      "post": {
        "operationId": "createShortCodeRequest",
        "summary": "Request a short code",
        "description": "Starts a short code application with a use case and an opt-in flow, and tells Sendly's review team. A workspace has one open application at a time. Nothing is charged: the setup fee is charged when the application is submitted. The application endpoints are the fuller way in.",
        "tags": [
          "Short codes"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "short_codes:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The request.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShortCodeRequestInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- ShortCodeRequestCreated: The application was started.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodeRequestCreated"
                },
                "examples": {
                  "default": {
                    "summary": "Built from createShortCodeRequest in server/routes.ts. Not captured, because a request starts a real application and notifies Sendly's review team.",
                    "value": {
                      "countryCode": "US",
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "id": "00000000-0000-4000-8000-000000000001",
                      "shortCode": null,
                      "status": "requested",
                      "useCase": "Order and delivery updates for Example Shop customers."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_request`: `useCase` or `optInFlow` is missing or blank, or `sampleMessages` is not an array of strings.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The opt-in flow is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "optInFlow is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (short_codes:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `settings:write` permission for short codes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `short_codes_not_enabled`: Short codes is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShortCodesNotEnabledError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `short_code_application_exists`: The workspace already has an open application, which the body names. Also when a concurrent request started one first.\n- `short_code_locked`, `short_code_conflict`: A concurrent request won the insert but no open application is found when it is read again (`short_code_conflict`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_application_exists"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "id": {
                          "type": "string",
                          "description": "The open application's id."
                        },
                        "status": {
                          "type": "string",
                          "description": "Where the code is in provisioning. Only `active` can send. Known values: `requested`, `provisioning`, `parked`, `active`, `suspended`, `cancelled`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "requested",
                            "provisioning",
                            "parked",
                            "active",
                            "suspended",
                            "cancelled"
                          ]
                        },
                        "reviewStatus": {
                          "type": "string",
                          "description": "Where Sendly's review of the application stands. Known values: `draft`, `awaiting_review`, `changes_requested`, `approved_for_filing`, `filed`, `rejected`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "draft",
                            "awaiting_review",
                            "changes_requested",
                            "approved_for_filing",
                            "filed",
                            "rejected"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "id",
                        "status",
                        "reviewStatus"
                      ],
                      "title": "short_code_application_exists",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_application_exists"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "short_code_locked",
                            "short_code_conflict"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "Short code application cannot change",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "short_code_locked",
                        "short_code_conflict"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The workspace already has an open application.",
                    "value": {
                      "error": "short_code_application_exists",
                      "message": "This workspace already has a short code application in progress.",
                      "id": "00000000-0000-4000-8000-000000000001",
                      "status": "requested",
                      "reviewStatus": "draft"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `short_code_internal_error`: The account's Short codes access could not be checked.\n- `short_code_internal_error`: Starting the application failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ShortCodeInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates": {
      "get": {
        "operationId": "listTemplates",
        "summary": "List templates",
        "description": "Lists every preset first, then the workspace's own templates, newest first. There is no paging.",
        "tags": [
          "Message templates"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "templates:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "list"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- TemplateList: Every preset, then the workspace's templates.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateList"
                },
                "examples": {
                  "default": {
                    "summary": "The presets, then the account's own templates.",
                    "value": {
                      "templates": [
                        {
                          "id": "tpl_preset_flash_sale",
                          "name": "Marketing · Flash Sale",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "first_name",
                              "type": "string",
                              "fallback": "there"
                            },
                            {
                              "key": "discount",
                              "type": "string",
                              "fallback": "20%"
                            },
                            {
                              "key": "link",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "flash_sale",
                          "status": "published",
                          "version": 1,
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_link_share",
                          "name": "Link Share",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "first_name",
                              "type": "string",
                              "fallback": "there"
                            },
                            {
                              "key": "link",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "link_share",
                          "status": "published",
                          "version": 1,
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_signup",
                          "name": "Signup Verification",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "signup",
                          "status": "published",
                          "version": 1,
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_password",
                          "name": "Password Reset",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "password",
                          "status": "published",
                          "version": 1,
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_transaction",
                          "name": "Transaction Confirmation",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "transaction",
                          "status": "published",
                          "version": 1,
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_delivery",
                          "name": "Delivery Confirmation",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "delivery",
                          "status": "published",
                          "version": 1,
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_otp",
                          "name": "Generic OTP",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "otp",
                          "status": "published",
                          "version": 1,
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_2fa",
                          "name": "2FA Login",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "2fa",
                          "status": "published",
                          "version": 1,
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_placeholder1",
                          "name": "Contract capture order ready",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "name",
                              "type": "string",
                              "fallback": "there"
                            },
                            {
                              "key": "order",
                              "type": "string"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": false,
                          "preset_slug": null,
                          "status": "draft",
                          "version": 1,
                          "published_at": null,
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_placeholder2",
                          "name": "e2e-probe-tpl",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "name",
                              "type": "string"
                            }
                          ],
                          "is_preset": false,
                          "preset_slug": null,
                          "status": "draft",
                          "version": 1,
                          "published_at": null,
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (templates:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The templates could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createTemplate",
        "summary": "Create a template",
        "description": "Creates a draft template. Its variables are read from the `{{key}}` placeholders in the text.",
        "tags": [
          "Message templates"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "templates:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "create"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The template to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTemplateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- SavedTemplate: The template was created as a draft.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedTemplate"
                },
                "examples": {
                  "default": {
                    "summary": "A draft with three variables, one given a fallback.",
                    "value": {
                      "id": "tpl_placeholder1",
                      "name": "Contract capture order ready",
                      "text": "Your Sendly code is 123456",
                      "variables": [
                        {
                          "key": "name",
                          "type": "string",
                          "fallback": "there"
                        },
                        {
                          "key": "order",
                          "type": "string"
                        },
                        {
                          "key": "code",
                          "type": "string"
                        }
                      ],
                      "is_preset": false,
                      "status": "draft",
                      "version": 1,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `name` or `text` is missing, not a string or blank, or `text` is longer than 1,600 characters.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The text is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Template text is required"
                    }
                  },
                  "text-too-long": {
                    "summary": "Text longer than 1,600 characters.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Template text exceeds maximum length of 1600 characters"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (templates:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The template could not be created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates/generate": {
      "post": {
        "operationId": "generateTemplate",
        "summary": "Generate a template",
        "description": "Suggests a template from a description of what it is for. Nothing is saved. Only the first 1,000 characters of `description` and the first 50 of `category` are used. An account may call it 10 times a minute across all of its keys. Behind the `ai_classification` flag.",
        "tags": [
          "Message templates"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "sms:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "generate"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "requestBody": {
          "description": "What to suggest a template for.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "description": {
                    "type": "string",
                    "pattern": "\\S",
                    "description": "What the template is for. Trimmed."
                  },
                  "category": {
                    "type": "string",
                    "description": "A hint, such as `transactional` or `marketing`. Only its first 50 characters are used, and a value that is not a string is ignored."
                  }
                },
                "required": [
                  "description"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- GeneratedTemplate: The suggested template.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeneratedTemplate"
                },
                "examples": {
                  "default": {
                    "summary": "A suggested template. Described from the handler and the suggestion's tool schema, since a capture would call a paid model.",
                    "value": {
                      "name": "appointment_reminder",
                      "text": "Hi {{name}}, your appointment is on {{date}}. Your code is {{code}}.",
                      "variables": [
                        "name",
                        "date",
                        "code"
                      ],
                      "category": "transactional"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `description` is missing, not a string or blank.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No description. Nothing is generated.",
                    "value": {
                      "error": "invalid_request",
                      "message": "description is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.\n- `api_key_required`: A CLI session token was used for an operation that sends messages, which needs an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/ApiKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (sms:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The `ai_classification` flag is off for the key's user.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "not_found"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Has no `message`.",
                  "title": "not_found, without a message",
                  "x-sendly-error-shape": "bare",
                  "x-sendly-error-codes": [
                    "not_found"
                  ],
                  "x-sendly-visibility": "preview"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `rate_limit_exceeded`: The key's owner has made more than 10 requests to this path in 60 seconds, counted across all of their keys.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `generation_failed`: No suggestion came back: the suggestion service is not configured, timed out, failed or answered without a template.\n- `internal_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "generation_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "generation_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "generation_failed"
                      ],
                      "x-sendly-visibility": "preview"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates/presets": {
      "get": {
        "operationId": "listTemplatePresets",
        "summary": "List preset templates",
        "description": "Lists Sendly's published presets, by name. Needs no API key: presets are the same for every account.",
        "tags": [
          "Message templates"
        ],
        "security": [],
        "x-sendly-auth": "public",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "presets"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- PresetTemplateList: Every published preset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresetTemplateList"
                },
                "examples": {
                  "default": {
                    "summary": "Every published preset, read without an API key.",
                    "value": {
                      "templates": [
                        {
                          "id": "tpl_preset_2fa",
                          "name": "2FA Login",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "2fa",
                          "category": "2fa",
                          "status": "published",
                          "version": 1,
                          "description": "Two-factor authentication login codes",
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_delivery",
                          "name": "Delivery Confirmation",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "delivery",
                          "category": "transactional",
                          "status": "published",
                          "version": 1,
                          "description": "Delivery confirmation codes",
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_otp",
                          "name": "Generic OTP",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "otp",
                          "category": "otp",
                          "status": "published",
                          "version": 1,
                          "description": "Generic one-time password verification",
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_link_share",
                          "name": "Link Share",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "first_name",
                              "type": "string",
                              "fallback": "there"
                            },
                            {
                              "key": "link",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "link_share",
                          "category": "marketing",
                          "status": "published",
                          "version": 1,
                          "description": "",
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_flash_sale",
                          "name": "Marketing · Flash Sale",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "first_name",
                              "type": "string",
                              "fallback": "there"
                            },
                            {
                              "key": "discount",
                              "type": "string",
                              "fallback": "20%"
                            },
                            {
                              "key": "link",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "flash_sale",
                          "category": "marketing",
                          "status": "published",
                          "version": 1,
                          "description": "",
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_password",
                          "name": "Password Reset",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "password",
                          "category": "transactional",
                          "status": "published",
                          "version": 1,
                          "description": "Password reset confirmation",
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_signup",
                          "name": "Signup Verification",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "signup",
                          "category": "signup",
                          "status": "published",
                          "version": 1,
                          "description": "New user signup verification",
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "tpl_preset_transaction",
                          "name": "Transaction Confirmation",
                          "text": "Your Sendly code is 123456",
                          "variables": [
                            {
                              "key": "app_name",
                              "type": "string",
                              "fallback": "App"
                            },
                            {
                              "key": "code",
                              "type": "string"
                            }
                          ],
                          "is_preset": true,
                          "preset_slug": "transaction",
                          "category": "transactional",
                          "status": "published",
                          "version": 1,
                          "description": "Transaction/payment confirmation",
                          "published_at": "2026-01-01T00:00:00.000Z",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyError"
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A GET with a body that is not valid JSON, answered by the body parser. Captured from the origin: the edge answers a GET with a body itself.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The presets could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates/{id}": {
      "get": {
        "operationId": "getTemplate",
        "summary": "Get a template",
        "description": "Returns one of the workspace's templates, or any preset.",
        "tags": [
          "Message templates"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "templates:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The template's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Template: The template.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                },
                "examples": {
                  "default": {
                    "summary": "The draft created by createTemplate.",
                    "value": {
                      "id": "tpl_placeholder1",
                      "name": "Contract capture order ready",
                      "text": "Your Sendly code is 123456",
                      "variables": [
                        {
                          "key": "name",
                          "type": "string",
                          "fallback": "there"
                        },
                        {
                          "key": "order",
                          "type": "string"
                        },
                        {
                          "key": "code",
                          "type": "string"
                        }
                      ],
                      "is_preset": false,
                      "preset_slug": null,
                      "status": "draft",
                      "version": 1,
                      "published_at": null,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "preset": {
                    "summary": "A preset, which every account can read.",
                    "value": {
                      "id": "tpl_preset_otp",
                      "name": "Generic OTP",
                      "text": "Your Sendly code is 123456",
                      "variables": [
                        {
                          "key": "app_name",
                          "type": "string",
                          "fallback": "App"
                        },
                        {
                          "key": "code",
                          "type": "string"
                        }
                      ],
                      "is_preset": true,
                      "preset_slug": "otp",
                      "status": "published",
                      "version": 1,
                      "published_at": "2026-01-01T00:00:00.000Z",
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (templates:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No preset and no template of the key's workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no template.",
                    "value": {
                      "error": "not_found",
                      "message": "Template not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The template could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateTemplate",
        "summary": "Update a template",
        "description": "Changes a draft template's name, text or variables. A published template is locked.",
        "tags": [
          "Message templates"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "templates:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "update"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The template's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTemplateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- SavedTemplate: The template was updated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedTemplate"
                },
                "examples": {
                  "default": {
                    "summary": "A new name and text. The stored fallback carries over to the re-read variables.",
                    "value": {
                      "id": "tpl_placeholder1",
                      "name": "Contract capture pickup ready",
                      "text": "Your Sendly code is 123456",
                      "variables": [
                        {
                          "key": "name",
                          "type": "string",
                          "fallback": "there"
                        },
                        {
                          "key": "order",
                          "type": "string"
                        }
                      ],
                      "is_preset": false,
                      "status": "draft",
                      "version": 1,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: The template is published, `name` or `text` is not a string or blank, `text` is longer than 1,600 characters, or the body changes nothing.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A body that changes nothing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "No valid updates provided"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (templates:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No template with this id belongs to the key's workspace. A preset answers this too: presets have no owner, so they never pass the ownership check.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no template.",
                    "value": {
                      "error": "not_found",
                      "message": "Template not found"
                    }
                  },
                  "preset": {
                    "summary": "A preset, which has no owner, so it answers as missing.",
                    "value": {
                      "error": "not_found",
                      "message": "Template not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The template could not be updated. A key without a workspace gets this for a template its user made in a workspace, which it can read but not change.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTemplate",
        "summary": "Delete a template",
        "description": "Deletes one of the workspace's templates, draft or published.",
        "tags": [
          "Message templates"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "templates:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "delete"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The template's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.\n\n- The template was deleted. A key without a workspace gets this for a template its user made in a workspace too, though nothing is deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (templates:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No template with this id belongs to the key's workspace. A preset answers this too: presets have no owner, so they never pass the ownership check.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "A template that was already deleted.",
                    "value": {
                      "error": "not_found",
                      "message": "Template not found"
                    }
                  },
                  "preset": {
                    "summary": "A preset, which has no owner, so it answers as missing.",
                    "value": {
                      "error": "not_found",
                      "message": "Template not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The template could not be deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates/{id}/clone": {
      "post": {
        "operationId": "cloneTemplate",
        "summary": "Clone a template",
        "description": "Copies one of the workspace's templates, or any preset, into a new draft template of the workspace.",
        "tags": [
          "Message templates"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "templates:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "clone"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The template's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "Optional. An empty body is fine.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "The copy's name, trimmed. Defaults to the original's name followed by ` (Copy)`, which a blank or non-string name gives too."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- TemplateWithoutPresetSlug: The copy, a draft with `published_at` `null`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateWithoutPresetSlug"
                },
                "examples": {
                  "default": {
                    "summary": "A copy of the published template, with a new name.",
                    "value": {
                      "id": "tpl_placeholder3",
                      "name": "Contract capture copy",
                      "text": "Your Sendly code is 123456",
                      "variables": [
                        {
                          "key": "name",
                          "type": "string",
                          "fallback": "there"
                        },
                        {
                          "key": "order",
                          "type": "string"
                        }
                      ],
                      "is_preset": false,
                      "status": "draft",
                      "version": 1,
                      "published_at": null,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "preset": {
                    "summary": "A copy of a preset, named after it.",
                    "value": {
                      "id": "tpl_placeholder4",
                      "name": "Generic OTP (Copy)",
                      "text": "Your Sendly code is 123456",
                      "variables": [
                        {
                          "key": "app_name",
                          "type": "string",
                          "fallback": "App"
                        },
                        {
                          "key": "code",
                          "type": "string"
                        }
                      ],
                      "is_preset": false,
                      "status": "draft",
                      "version": 1,
                      "published_at": null,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (templates:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No preset and no template of the key's workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no template.",
                    "value": {
                      "error": "not_found",
                      "message": "Template not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The template could not be cloned.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates/{id}/preview": {
      "post": {
        "operationId": "previewTemplate",
        "summary": "Preview a template",
        "description": "Renders one of the workspace's templates, or any preset, with the values you give. Nothing is sent or saved.",
        "tags": [
          "Message templates"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "templates:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "preview"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The template's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The values to render with. An empty body renders with the fallbacks only.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "variables": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Values by variable key: `{\"code\": \"123456\"}` fills `{{code}}`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- TemplatePreview: The rendered text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplatePreview"
                },
                "examples": {
                  "default": {
                    "summary": "The draft rendered with one value; `name` falls back to its fallback.",
                    "value": {
                      "template_id": "tpl_placeholder1",
                      "original_text": "Hi {{name}}, pickup {{order}} is ready",
                      "rendered_text": "Hi there, pickup A-100 is ready",
                      "character_count": 31,
                      "segment_count": 1
                    }
                  },
                  "preset": {
                    "summary": "A preset rendered with a code.",
                    "value": {
                      "template_id": "tpl_preset_otp",
                      "original_text": "Your {{app_name}} verification code is {{code}}. It expires in 5 minutes.",
                      "rendered_text": "Your App verification code is 123456. It expires in 5 minutes.",
                      "character_count": 62,
                      "segment_count": 1
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (templates:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No preset and no template of the key's workspace has this id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no template.",
                    "value": {
                      "error": "not_found",
                      "message": "Template not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The template could not be rendered.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates/{id}/publish": {
      "post": {
        "operationId": "publishTemplate",
        "summary": "Publish a template",
        "description": "Publishes a draft template, which locks it against edits.",
        "tags": [
          "Message templates"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "templates:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "templates",
          "method": "publish"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The template's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- TemplateWithoutPresetSlug: The template is published.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateWithoutPresetSlug"
                },
                "examples": {
                  "default": {
                    "summary": "The draft, published.",
                    "value": {
                      "id": "tpl_placeholder1",
                      "name": "Contract capture pickup ready",
                      "text": "Your Sendly code is 123456",
                      "variables": [
                        {
                          "key": "name",
                          "type": "string",
                          "fallback": "there"
                        },
                        {
                          "key": "order",
                          "type": "string"
                        }
                      ],
                      "is_preset": false,
                      "status": "published",
                      "version": 1,
                      "published_at": "2026-01-01T00:00:00.000Z",
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: The template is already published.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The same template, published again.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Template is already published"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (templates:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No template with this id belongs to the key's workspace. A preset answers this too: presets have no owner, so they never pass the ownership check.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no template.",
                    "value": {
                      "error": "not_found",
                      "message": "Template not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The template could not be published. A key without a workspace gets this for a template its user made in a workspace, which it can read but not change.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tendlc/assignments": {
      "get": {
        "operationId": "listTenDlcAssignments",
        "summary": "List 10DLC number assignments",
        "description": "Lists the workspace's number assignments, newest first, with no paging. Behind the `tendlc_self_serve` flag: an account without it gets 404 `not_found`, the same answer as an unknown id.",
        "tags": [
          "10DLC brands and campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "tendlc:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "tenDlc",
          "method": "listAssignments"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- TenDlcAssignmentList: The assignments.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenDlcAssignmentList"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and serializer code: one live assignment and one the carriers refused. A capture key belongs to no workspace, so it cannot list.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000302",
                          "campaignId": "00000000-0000-4000-8000-000000000201",
                          "phoneNumber": "+15555550103",
                          "status": "Action needed",
                          "assignedAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000301",
                          "campaignId": "00000000-0000-4000-8000-000000000201",
                          "phoneNumber": "+15555550100",
                          "status": "Active",
                          "assignedAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace, as an enterprise master key or a key made before workspaces. A key made in any workspace, a personal one included, works.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` says how to get a key that belongs to a workspace.",
                      "title": "workspace_required, with a message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the 10DLC routes' 400 `workspace_required` carries this `message`. The production capture of 2026-10-02 predates that change. It was: The capture's test key belongs to no workspace, which every 10DLC operation needs. Nothing is read or written.",
                    "value": {
                      "error": "workspace_required",
                      "message": "10DLC routes need an API key that belongs to a workspace, and this key is not attached to one. Enterprise master keys and keys created before workspaces have no workspace. Create a new key under API Keys in the workspace you are registering for (your personal workspace works too) and use that key."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (tendlc:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The account does not have the `tendlc_self_serve` flag.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `failed_to_list_assignments`: The assignments could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "failed_to_list_assignments"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "failed_to_list_assignments",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "failed_to_list_assignments"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tendlc/brands": {
      "get": {
        "operationId": "listTenDlcBrands",
        "summary": "List 10DLC brands",
        "description": "Lists the workspace's brands, newest first, with no paging. Behind the `tendlc_self_serve` flag: an account without it gets 404 `not_found`, the same answer as an unknown id.",
        "tags": [
          "10DLC brands and campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "tendlc:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "tenDlc",
          "method": "listBrands"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- TenDlcBrandList: The brands.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenDlcBrandList"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and serializer code: a workspace with a verified business brand and a sole-proprietor brand whose registration never completed, which the hourly sweep marks failed with that reason. A capture key belongs to no workspace, so it cannot list.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000101",
                          "legalName": "Example Holdings LLC",
                          "dba": "Example",
                          "entityType": "PRIVATE_PROFIT",
                          "ein": "12-3456789",
                          "vertical": "RETAIL",
                          "website": "https://example.com",
                          "status": "verified",
                          "identityStatus": "VERIFIED",
                          "smsOtpStatus": null,
                          "mobileLast4": null,
                          "failureReasons": null,
                          "vetting": null,
                          "einDocument": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000102",
                          "legalName": "Ada Example",
                          "dba": null,
                          "entityType": "SOLE_PROPRIETOR",
                          "ein": null,
                          "vertical": null,
                          "website": null,
                          "status": "failed",
                          "identityStatus": null,
                          "smsOtpStatus": "not_started",
                          "mobileLast4": "0102",
                          "failureReasons": [
                            "creation did not complete — please try again"
                          ],
                          "vetting": null,
                          "einDocument": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace, as an enterprise master key or a key made before workspaces. A key made in any workspace, a personal one included, works.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` says how to get a key that belongs to a workspace.",
                      "title": "workspace_required, with a message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the 10DLC routes' 400 `workspace_required` carries this `message`. The production capture of 2026-10-02 predates that change. It was: The capture's test key belongs to no workspace, which every 10DLC operation needs. Nothing is read or written.",
                    "value": {
                      "error": "workspace_required",
                      "message": "10DLC routes need an API key that belongs to a workspace, and this key is not attached to one. Enterprise master keys and keys created before workspaces have no workspace. Create a new key under API Keys in the workspace you are registering for (your personal workspace works too) and use that key."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  },
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (tendlc:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The account does not have the `tendlc_self_serve` flag.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `failed_to_list_brands`: The brands could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "failed_to_list_brands"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "failed_to_list_brands",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "failed_to_list_brands"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createTenDlcBrand",
        "summary": "Register a 10DLC brand",
        "description": "Charges the one-time brand setup fee to the account's card, then registers the brand with the carrier network. Live keys only. Send an Idempotency-Key so a retry gets the first answer. Without one, the setup charge is keyed to the workspace, the legal name, the fee tier and the day: a repeat that day is not charged twice, and gets back the brand that charge already registered, unless that brand failed. Behind the `tendlc_self_serve` flag: an account without it gets 404 `not_found`, the same answer as an unknown id.",
        "tags": [
          "10DLC brands and campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "tendlc:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "tenDlc",
          "method": "createBrand"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The business to register.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTenDlcBrandRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- TenDlcBrandResponse: The brand was registered: usually `pending` while the carrier network reviews it, `verified` when the network verified its identity at once, `failed` when it rejected it at once.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenDlcBrandResponse"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and serializer code: a business brand registered and waiting for the carrier review. Registering charges a setup fee and submits a real registration, so it is never captured.",
                    "value": {
                      "data": {
                        "id": "00000000-0000-4000-8000-000000000101",
                        "legalName": "Example Holdings LLC",
                        "dba": "Example",
                        "entityType": "PRIVATE_PROFIT",
                        "ein": "12-3456789",
                        "vertical": "RETAIL",
                        "website": "https://example.com",
                        "status": "pending",
                        "identityStatus": null,
                        "smsOtpStatus": null,
                        "mobileLast4": null,
                        "failureReasons": null,
                        "vetting": null,
                        "einDocument": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `workspace_required`: The API key belongs to no workspace, as an enterprise master key or a key made before workspaces. A key made in any workspace, a personal one included, works.\n- legalName is required: `legalName` is missing, empty or not a string.\n- `invalid_request`: A sole proprietor's registration has no `mobilePhone`. Checked before any charge.\n- `brand_create_failed`: The carrier network refused the registration. The setup fee is refunded, or support refunds it.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` says how to get a key that belongs to a workspace.",
                      "title": "workspace_required, with a message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "legalName is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "legalName is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "brand_create_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` is the carrier network's reason, without carrier names.",
                      "title": "brand_create_failed: carrier network",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "brand_create_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-json": {
                    "summary": "A body that is not valid JSON, answered by the body parser.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  },
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the 10DLC routes' 400 `workspace_required` carries this `message`. The production capture of 2026-10-02 predates that change. It was: The capture's test key belongs to no workspace, which every 10DLC operation needs. Nothing is read or written.",
                    "value": {
                      "error": "workspace_required",
                      "message": "10DLC routes need an API key that belongs to a workspace, and this key is not attached to one. Enterprise master keys and keys created before workspaces have no workspace. Create a new key under API Keys in the workspace you are registering for (your personal workspace works too) and use that key."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `payment_method_required`, `payment_failed`: The account has no card on file (`payment_method_required`), or charging it the setup fee failed (`payment_failed`). Enterprise-billed workspaces are not charged.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "payment_method_required",
                        "payment_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "actionUrl": {
                      "type": "string",
                      "enum": [
                        "/billing"
                      ]
                    },
                    "feature": {
                      "type": "string",
                      "enum": [
                        "tendlc_brand"
                      ]
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "actionUrl",
                    "feature"
                  ],
                  "title": "10DLC setup fee not paid",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "payment_method_required",
                    "payment_failed"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (tendlc:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `live_key_required`: A test key or a CLI session called it.\n- `insufficient_permission`: In a team workspace, the key owner's role lacks the `verify:write` permission, or the owner is no longer a member.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_permission"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "Singular `insufficient_permission`, unlike the `insufficient_permissions` a missing key scope gets.",
                      "title": "insufficient_permission",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_permission"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The account does not have the `tendlc_self_serve` flag.\n- `not_found`: The new brand's row vanished before it could be registered.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `brand_create_failed`: The brand could not be saved, the carrier network could not be reached, or the request failed unexpectedly, as for an `entityType` that is not a string.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "brand_create_failed"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "brand_create_failed",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "brand_create_failed"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `brand_create_failed`: The carrier network answered with a server error. The brand stays `pending` and is reconciled later.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "brand_create_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "description": "`message` is the carrier network's reason, without carrier names.",
                  "title": "brand_create_failed: carrier network",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "brand_create_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tendlc/brands/{id}": {
      "get": {
        "operationId": "getTenDlcBrand",
        "summary": "Get a 10DLC brand",
        "description": "Returns one brand, after checking the carrier network for a newer identity status, so polling it shows progress. A failed check returns the stored brand. Behind the `tendlc_self_serve` flag: an account without it gets 404 `not_found`, the same answer as an unknown id.",
        "tags": [
          "10DLC brands and campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "tendlc:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "tenDlc",
          "method": "getBrand"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The brand's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- TenDlcBrandResponse: The brand.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenDlcBrandResponse"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and serializer code: a verified business brand. A capture key belongs to no workspace, so it cannot read one.",
                    "value": {
                      "data": {
                        "id": "00000000-0000-4000-8000-000000000101",
                        "legalName": "Example Holdings LLC",
                        "dba": "Example",
                        "entityType": "PRIVATE_PROFIT",
                        "ein": "12-3456789",
                        "vertical": "RETAIL",
                        "website": "https://example.com",
                        "status": "verified",
                        "identityStatus": "VERIFIED",
                        "smsOtpStatus": null,
                        "mobileLast4": null,
                        "failureReasons": null,
                        "vetting": null,
                        "einDocument": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace, as an enterprise master key or a key made before workspaces. A key made in any workspace, a personal one included, works.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` says how to get a key that belongs to a workspace.",
                      "title": "workspace_required, with a message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the 10DLC routes' 400 `workspace_required` carries this `message`. The production capture of 2026-10-02 predates that change. It was: The capture's test key belongs to no workspace, which every 10DLC operation needs. Nothing is read or written.",
                    "value": {
                      "error": "workspace_required",
                      "message": "10DLC routes need an API key that belongs to a workspace, and this key is not attached to one. Enterprise master keys and keys created before workspaces have no workspace. Create a new key under API Keys in the workspace you are registering for (your personal workspace works too) and use that key."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (tendlc:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The account does not have the `tendlc_self_serve` flag.\n- `not_found`: No brand with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `failed_to_load_brand`: The brand could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "failed_to_load_brand"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "failed_to_load_brand",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "failed_to_load_brand"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tendlc/brands/{id}/qualify/{usecase}": {
      "get": {
        "operationId": "qualifyTenDlcUseCase",
        "summary": "Check a 10DLC use case",
        "description": "Asks the carrier network whether a use case qualifies for a registered brand, before a campaign is created. Behind the `tendlc_self_serve` flag: an account without it gets 404 `not_found`, the same answer as an unknown id.",
        "tags": [
          "10DLC brands and campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "tendlc:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "tenDlc",
          "method": "qualify"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The brand's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The use case, such as `MIXED` or `MARKETING`."
            },
            "required": true,
            "name": "usecase",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- TenDlcQualifyResponse: The answer.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenDlcQualifyResponse"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and serializer code: a use case that qualifies with all three carriers, as the mock account's brands answer. A capture key belongs to no workspace, so it cannot ask.",
                    "value": {
                      "data": {
                        "useCase": "MIXED",
                        "qualified": true,
                        "reason": null,
                        "throughput": {
                          "tier": "Standard",
                          "carriersReady": 3
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace, as an enterprise master key or a key made before workspaces. A key made in any workspace, a personal one included, works.\n- `qualify_failed`: The carrier network refused the check, as for a use case it does not know.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` says how to get a key that belongs to a workspace.",
                      "title": "workspace_required, with a message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "qualify_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` is the carrier network's reason, without carrier names.",
                      "title": "qualify_failed: carrier network",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "qualify_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the 10DLC routes' 400 `workspace_required` carries this `message`. The production capture of 2026-10-02 predates that change. It was: The capture's test key belongs to no workspace, which every 10DLC operation needs. Nothing is read or written.",
                    "value": {
                      "error": "workspace_required",
                      "message": "10DLC routes need an API key that belongs to a workspace, and this key is not attached to one. Enterprise master keys and keys created before workspaces have no workspace. Create a new key under API Keys in the workspace you are registering for (your personal workspace works too) and use that key."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (tendlc:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The account does not have the `tendlc_self_serve` flag.\n- `not_found`: No brand with this id belongs to the workspace, or the brand is not registered with the carrier network yet.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `qualify_failed`: The carrier network could not be reached, or the check failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "qualify_failed"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "qualify_failed",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "qualify_failed"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `qualify_failed`: The carrier network answered with a server error.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "qualify_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "description": "`message` is the carrier network's reason, without carrier names.",
                  "title": "qualify_failed: carrier network",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "qualify_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tendlc/campaigns": {
      "get": {
        "operationId": "listTenDlcCampaigns",
        "summary": "List 10DLC campaigns",
        "description": "Lists the workspace's campaigns, newest first, with no paging. Behind the `tendlc_self_serve` flag: an account without it gets 404 `not_found`, the same answer as an unknown id.",
        "tags": [
          "10DLC brands and campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "tendlc:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "tenDlc",
          "method": "listCampaigns"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- TenDlcCampaignList: The campaigns.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenDlcCampaignList"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and serializer code: a workspace with an active campaign and a rejected one that has used its resubmissions. A carrier rejection records no reason on the campaign, so its `failureReasons` is null. A capture key belongs to no workspace, so it cannot list.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000202",
                          "brandId": "00000000-0000-4000-8000-000000000101",
                          "useCase": "MIXED",
                          "subUseCases": [
                            "CUSTOMER_CARE",
                            "DELIVERY_NOTIFICATION"
                          ],
                          "description": "Order updates and support replies for Example customers.",
                          "status": "failed",
                          "sampleMessages": [
                            "Example: your order has shipped and arrives Friday. Reply STOP to opt out.",
                            "Example support: we replied to your ticket. Reply HELP for help, STOP to opt out."
                          ],
                          "throughput": null,
                          "failureReasons": null,
                          "reviewNote": null,
                          "resubmissionCount": 2,
                          "resubmissionLimitReached": true,
                          "deletable": false,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z"
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000201",
                          "brandId": "00000000-0000-4000-8000-000000000101",
                          "useCase": "MIXED",
                          "subUseCases": [
                            "CUSTOMER_CARE",
                            "DELIVERY_NOTIFICATION"
                          ],
                          "description": "Order updates and support replies for Example customers.",
                          "status": "active",
                          "sampleMessages": [
                            "Example: your order has shipped and arrives Friday. Reply STOP to opt out.",
                            "Example support: we replied to your ticket. Reply HELP for help, STOP to opt out."
                          ],
                          "throughput": {
                            "tier": "Standard",
                            "carriersReady": 3
                          },
                          "failureReasons": null,
                          "reviewNote": null,
                          "resubmissionCount": 0,
                          "resubmissionLimitReached": false,
                          "deletable": false,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace, as an enterprise master key or a key made before workspaces. A key made in any workspace, a personal one included, works.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` says how to get a key that belongs to a workspace.",
                      "title": "workspace_required, with a message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the 10DLC routes' 400 `workspace_required` carries this `message`. The production capture of 2026-10-02 predates that change. It was: The capture's test key belongs to no workspace, which every 10DLC operation needs. Nothing is read or written.",
                    "value": {
                      "error": "workspace_required",
                      "message": "10DLC routes need an API key that belongs to a workspace, and this key is not attached to one. Enterprise master keys and keys created before workspaces have no workspace. Create a new key under API Keys in the workspace you are registering for (your personal workspace works too) and use that key."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (tendlc:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The account does not have the `tendlc_self_serve` flag.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `failed_to_list_campaigns`: The campaigns could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "failed_to_list_campaigns"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "failed_to_list_campaigns",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "failed_to_list_campaigns"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createTenDlcCampaign",
        "summary": "Create a 10DLC campaign",
        "description": "Creates a campaign under a verified brand. A business brand's campaign waits for Sendly's review (`awaiting_review`) before it reaches the carriers; a sole proprietor's goes to the carriers at once. Live keys only. Not idempotent. Behind the `tendlc_self_serve` flag: an account without it gets 404 `not_found`, the same answer as an unknown id.",
        "tags": [
          "10DLC brands and campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "tendlc:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "tenDlc",
          "method": "createCampaign"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "requestBody": {
          "description": "The campaign to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTenDlcCampaignRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- TenDlcCampaignResponse: The campaign was created: `awaiting_review` for a business brand, `active` or `pending` for a sole proprietor, `pending` when Sendly's review is switched off.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenDlcCampaignResponse"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and serializer code: a business brand's campaign, queued for Sendly's review. Creating one submits a real registration, so it is never captured.",
                    "value": {
                      "data": {
                        "id": "00000000-0000-4000-8000-000000000201",
                        "brandId": "00000000-0000-4000-8000-000000000101",
                        "useCase": "MIXED",
                        "subUseCases": [
                          "CUSTOMER_CARE",
                          "DELIVERY_NOTIFICATION"
                        ],
                        "description": "Order updates and support replies for Example customers.",
                        "status": "awaiting_review",
                        "sampleMessages": [
                          "Example: your order has shipped and arrives Friday. Reply STOP to opt out.",
                          "Example support: we replied to your ticket. Reply HELP for help, STOP to opt out."
                        ],
                        "throughput": null,
                        "failureReasons": null,
                        "reviewNote": null,
                        "resubmissionCount": 0,
                        "resubmissionLimitReached": false,
                        "deletable": true,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace, as an enterprise master key or a key made before workspaces. A key made in any workspace, a personal one included, works.\n- Campaign fields required: `brandId`, `useCase`, `description` or `messageFlow` is missing or empty, or `sampleMessages` is not an array.\n- `brand_not_verified`: The brand is registered but not verified yet.\n- `campaign_create_failed`: The carrier network refused a campaign sent to it at once: a sole proprietor's, or any campaign while Sendly's review is switched off.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` says how to get a key that belongs to a workspace.",
                      "title": "workspace_required, with a message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "brandId, useCase, description, messageFlow, and sampleMessages are required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "Campaign fields required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "brand_not_verified"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "brand_not_verified",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "brand_not_verified"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "campaign_create_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` is the carrier network's reason, without carrier names.",
                      "title": "campaign_create_failed: carrier network",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "campaign_create_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the 10DLC routes' 400 `workspace_required` carries this `message`. The production capture of 2026-10-02 predates that change. It was: The capture's test key belongs to no workspace, which every 10DLC operation needs. Nothing is read or written.",
                    "value": {
                      "error": "workspace_required",
                      "message": "10DLC routes need an API key that belongs to a workspace, and this key is not attached to one. Enterprise master keys and keys created before workspaces have no workspace. Create a new key under API Keys in the workspace you are registering for (your personal workspace works too) and use that key."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (tendlc:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `live_key_required`: A test key or a CLI session called it.\n- `insufficient_permission`: In a team workspace, the key owner's role lacks the `verify:write` permission, or the owner is no longer a member.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_permission"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "Singular `insufficient_permission`, unlike the `insufficient_permissions` a missing key scope gets.",
                      "title": "insufficient_permission",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_permission"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The account does not have the `tendlc_self_serve` flag.\n- `not_found`: No brand with `brandId` belongs to the workspace, or it is not registered with the carrier network yet.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `sole_prop_single_campaign`, `resubmit_required`: A sole-proprietor brand already has a campaign that is not failed or expired (`sole_prop_single_campaign`), or a business brand has a rejected campaign to resubmit instead (`resubmit_required`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "sole_prop_single_campaign",
                        "resubmit_required"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "Campaign already exists",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "sole_prop_single_campaign",
                    "resubmit_required"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `sample_lint_failed`: One of the first five sample messages is blank, is not a string or has an unfilled placeholder, or fewer than two of them have text.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "sample_lint_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "sample_lint_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "sample_lint_failed"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `campaign_create_failed`: The campaign could not be saved, the carrier network could not be reached, or the request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "campaign_create_failed"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "campaign_create_failed",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "campaign_create_failed"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `campaign_create_failed`: The carrier network answered with a server error, for a campaign sent to it at once.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "campaign_create_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "description": "`message` is the carrier network's reason, without carrier names.",
                  "title": "campaign_create_failed: carrier network",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "campaign_create_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tendlc/campaigns/{id}": {
      "get": {
        "operationId": "getTenDlcCampaign",
        "summary": "Get a 10DLC campaign",
        "description": "Returns one campaign, after checking the carrier network for a newer status and throughput, so polling it shows progress. A failed check returns the stored campaign. Behind the `tendlc_self_serve` flag: an account without it gets 404 `not_found`, the same answer as an unknown id.",
        "tags": [
          "10DLC brands and campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "tendlc:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "tenDlc",
          "method": "getCampaign"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- TenDlcCampaignResponse: The campaign.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenDlcCampaignResponse"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and serializer code: an active campaign with its throughput. A capture key belongs to no workspace, so it cannot read one.",
                    "value": {
                      "data": {
                        "id": "00000000-0000-4000-8000-000000000201",
                        "brandId": "00000000-0000-4000-8000-000000000101",
                        "useCase": "MIXED",
                        "subUseCases": [
                          "CUSTOMER_CARE",
                          "DELIVERY_NOTIFICATION"
                        ],
                        "description": "Order updates and support replies for Example customers.",
                        "status": "active",
                        "sampleMessages": [
                          "Example: your order has shipped and arrives Friday. Reply STOP to opt out.",
                          "Example support: we replied to your ticket. Reply HELP for help, STOP to opt out."
                        ],
                        "throughput": {
                          "tier": "Standard",
                          "carriersReady": 3
                        },
                        "failureReasons": null,
                        "reviewNote": null,
                        "resubmissionCount": 0,
                        "resubmissionLimitReached": false,
                        "deletable": false,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace, as an enterprise master key or a key made before workspaces. A key made in any workspace, a personal one included, works.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` says how to get a key that belongs to a workspace.",
                      "title": "workspace_required, with a message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_required"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the 10DLC routes' 400 `workspace_required` carries this `message`. The production capture of 2026-10-02 predates that change. It was: The capture's test key belongs to no workspace, which every 10DLC operation needs. Nothing is read or written.",
                    "value": {
                      "error": "workspace_required",
                      "message": "10DLC routes need an API key that belongs to a workspace, and this key is not attached to one. Enterprise master keys and keys created before workspaces have no workspace. Create a new key under API Keys in the workspace you are registering for (your personal workspace works too) and use that key."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (tendlc:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The account does not have the `tendlc_self_serve` flag.\n- `not_found`: No campaign with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `failed_to_load_campaign`: The campaign could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "failed_to_load_campaign"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "failed_to_load_campaign",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "failed_to_load_campaign"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tendlc/campaigns/{id}/assign": {
      "post": {
        "operationId": "assignTenDlcNumber",
        "summary": "Assign a number to a 10DLC campaign",
        "description": "Registers a US local number of this workspace to an active campaign, which lets it send. Live keys only. Assigning a number to the campaign it is already on returns the existing assignment, with 201. Behind the `tendlc_self_serve` flag: an account without it gets 404 `not_found`, the same answer as an unknown id.",
        "tags": [
          "10DLC brands and campaigns"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "tendlc:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "tenDlc",
          "method": "assignNumber"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The campaign's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The number to assign.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssignTenDlcNumberRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- TenDlcAssignmentResponse: The number was assigned, or already was to this campaign. It can send once `status` is `Active`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenDlcAssignmentResponse"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler and serializer code: a number just assigned, under review until the carriers accept it. Assigning registers a real number, so it is never captured.",
                    "value": {
                      "data": {
                        "id": "00000000-0000-4000-8000-000000000301",
                        "campaignId": "00000000-0000-4000-8000-000000000201",
                        "phoneNumber": "+15555550100",
                        "status": "Under review",
                        "assignedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `workspace_required`: The API key belongs to no workspace, as an enterprise master key or a key made before workspaces. A key made in any workspace, a personal one included, works.\n- phoneNumber is required: `phoneNumber` is missing, empty or not a string.\n- `campaign_not_active`: The campaign is not `active` yet.\n- `number_not_ready`: The number is not set up for messaging yet.\n- `assignment_failed`: The carrier network refused the assignment.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "workspace_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` says how to get a key that belongs to a workspace.",
                      "title": "workspace_required, with a message",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "workspace_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "phoneNumber is required"
                          ]
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "`error` holds a sentence, and there is no `message`.",
                      "title": "phoneNumber is required",
                      "x-sendly-error-shape": "sentence",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "campaign_not_active"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "campaign_not_active",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "campaign_not_active"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_not_ready"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_not_ready",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_not_ready"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "assignment_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "`message` is the carrier network's reason, without carrier names.",
                      "title": "assignment_failed: carrier network",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "assignment_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) the 10DLC routes' 400 `workspace_required` carries this `message`. The production capture of 2026-10-02 predates that change. It was: The capture's test key belongs to no workspace, which every 10DLC operation needs. Nothing is read or written.",
                    "value": {
                      "error": "workspace_required",
                      "message": "10DLC routes need an API key that belongs to a workspace, and this key is not attached to one. Enterprise master keys and keys created before workspaces have no workspace. Create a new key under API Keys in the workspace you are registering for (your personal workspace works too) and use that key."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (tendlc:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `live_key_required`: A test key or a CLI session called it.\n- `insufficient_permission`: In a team workspace, the key owner's role lacks the `verify:write` permission, or the owner is no longer a member.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insufficient_permission"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "description": "Singular `insufficient_permission`, unlike the `insufficient_permissions` a missing key scope gets.",
                      "title": "insufficient_permission",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insufficient_permission"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: The account does not have the `tendlc_self_serve` flag.\n- `number_not_found`: No number of this workspace is `phoneNumber`.\n- `not_found`: No campaign with this id belongs to the workspace, it never reached the carrier network, or the number left the workspace meanwhile.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_not_found"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "number_not_found",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "number_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `number_already_assigned`: The number is assigned to another campaign. Remove it there first.\n- `messaging_exception`, `messaging_activating`, `sole_prop_single_number`: A ported number's messaging failed to activate (`messaging_exception`) or is still activating (`messaging_activating`), or a sole proprietor's campaign already has its one number (`sole_prop_single_number`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_already_assigned"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_already_assigned",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_already_assigned"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "messaging_exception",
                            "messaging_activating",
                            "sole_prop_single_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "Number not assignable yet",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "messaging_exception",
                        "messaging_activating",
                        "sole_prop_single_number"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `ineligible_number`: The number is not a US local number: toll-free and non-US numbers cannot join a 10DLC campaign.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "ineligible_number"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "ineligible_number",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "ineligible_number"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `assignment_failed`: The carrier network could not be reached, or the assignment failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "assignment_failed"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "assignment_failed",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "assignment_failed"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `assignment_failed`: The carrier network answered with a server error.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "assignment_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "description": "`message` is the carrier network's reason, without carrier names.",
                  "title": "assignment_failed: carrier network",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "assignment_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verification/best-prefill": {
      "get": {
        "operationId": "getBestPrefill",
        "summary": "Get the best prefill for a business upgrade",
        "description": "Merges the messaging details of every active, verified business verification the caller's user owns, in any workspace, picking the most recently updated non-empty value for each field. Use it to fill in a business upgrade form. It reads by user, not by workspace: a workspace key reads the verifications its owner has in every workspace. Any API key can call it, whatever its scopes, and a test key reads live data.",
        "tags": [
          "Business upgrade preflight"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "businessUpgrade",
          "method": "bestPrefill"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- BestPrefill: The merged values. `prefill` is empty and `sourceWorkspaceCount` is 0 when the user has no verified business verification.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BestPrefill"
                },
                "examples": {
                  "default": {
                    "summary": "The merged values from the test account's verified business verifications.",
                    "value": {
                      "prefill": {
                        "monthlyVolume": "10,000",
                        "useCase": "2FA",
                        "useCaseSummary": "Two-factor authentication codes, suspicious login alerts, and account activity confirmations to keep user accounts secure",
                        "sampleMessages": "Your verification code is 123456. Valid for 10 minutes. Never share this code with anyone.\n\nNew login detected from Chrome on Windows in New York. Reply YES to confirm or BLOCK to secure your account immediately.",
                        "optInImageUrls": "https://lrelpuuyqqtkdsvakzun.supabase.co/storage/v1/object/public/opt-in-screenshots/00000000-0000-4000-8000-000000000001/dsfdsf-i1mp-1769870248653.webp",
                        "optInSource": "hosted",
                        "privacyUrl": "https://sendly.live/legal/dsfdsf-65ta-privacy",
                        "termsUrl": "https://sendly.live/legal/dsfdsf-65ta-terms",
                        "additionalInformation": "N/A",
                        "isvReseller": "sendly",
                        "ageGatedContent": false
                      },
                      "sourceWorkspaceCount": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key passed in the URL.",
                    "value": {
                      "error": "invalid_request",
                      "message": "API keys must not be passed in URL parameters. Use the Authorization header."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The verifications could not be read. `message` is the database error's own text.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verification/preflight": {
      "post": {
        "operationId": "runPreflight",
        "summary": "Check business details before an upgrade",
        "description": "Checks the business details a business upgrade would submit and reports what a reviewer would reject or flag, with suggested fixes. It saves nothing and submits nothing. It does reach out: it loads the privacy and terms URLs, looks up the website's domain registration, and looks the business up in a public registry. Any API key can call it, whatever its scopes.",
        "tags": [
          "Business upgrade preflight"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "businessUpgrade",
          "method": "preflight"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The business details to check.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreflightCandidate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- PreflightReport: The report, whatever its verdict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreflightReport"
                },
                "examples": {
                  "empty": {
                    "summary": "An empty body: every required field is reported missing.",
                    "value": {
                      "verificationId": "candidate",
                      "country": "UNKNOWN",
                      "verdict": "blocked",
                      "domainAge": null,
                      "registry": null,
                      "issues": [
                        {
                          "severity": "blocker",
                          "field": "businessName",
                          "code": "field_required",
                          "message": "Legal business name is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "corporateWebsite",
                          "code": "field_required",
                          "message": "Website is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessAddr1",
                          "code": "field_required",
                          "message": "Address is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessCity",
                          "code": "field_required",
                          "message": "City is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessState",
                          "code": "field_required",
                          "message": "State or province is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessZip",
                          "code": "field_required",
                          "message": "ZIP or postal code is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessContactFirstName",
                          "code": "field_required",
                          "message": "Contact first name is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessContactLastName",
                          "code": "field_required",
                          "message": "Contact last name is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessContactEmail",
                          "code": "field_required",
                          "message": "Contact email is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessContactPhone",
                          "code": "field_required",
                          "message": "Contact phone is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "messageVolume",
                          "code": "field_required",
                          "message": "Monthly message volume is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "useCase",
                          "code": "field_required",
                          "message": "Use case is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "useCaseSummary",
                          "code": "field_required",
                          "message": "Use case description is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "productionMessageContent",
                          "code": "field_required",
                          "message": "Sample messages is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "optInWorkflow",
                          "code": "field_required",
                          "message": "Opt-in workflow is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "additionalInformation",
                          "code": "field_required",
                          "message": "Additional information is required.",
                          "suggestion": "Fill in this field, then check again."
                        }
                      ],
                      "proposedFixes": []
                    }
                  },
                  "fixes": {
                    "summary": "A US candidate with a 2-letter state, a phone number without its +, a use case that is not on the list, a sole proprietor with an EIN and samples without STOP, each with a proposed fix where there is one.",
                    "value": {
                      "verificationId": "candidate",
                      "businessName": "Contract Fixture Example LLC",
                      "country": "US",
                      "verdict": "blocked",
                      "domainAge": null,
                      "registry": null,
                      "issues": [
                        {
                          "severity": "blocker",
                          "field": "corporateWebsite",
                          "code": "field_required",
                          "message": "Website is required.",
                          "suggestion": "Fill in this field, then check again."
                        },
                        {
                          "severity": "blocker",
                          "field": "useCase",
                          "code": "field_not_in_enum",
                          "message": "Use case is not one of the accepted values.",
                          "suggestion": "Try 'Appointments'."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessState",
                          "code": "state_must_be_full_name",
                          "message": "Enter the full state or province name, not the 2-letter code.",
                          "suggestion": "Use 'Texas'."
                        },
                        {
                          "severity": "blocker",
                          "field": "businessContactPhone",
                          "code": "phone_missing_plus",
                          "message": "The contact phone number needs a + and the country code.",
                          "suggestion": "Use '+15555550185'."
                        },
                        {
                          "severity": "warning",
                          "field": "optInImageUrls",
                          "code": "manual_opt_in_check_ctia",
                          "message": "Your opt-in screenshot may be missing required disclosures: how to opt out (Reply STOP), how to get help (Reply HELP), that message and data rates may apply, that message frequency varies, and links to your privacy policy and terms. Submissions without them are rejected.",
                          "suggestion": "Use a Sendly-hosted opt-in page, which includes these by default, or update your screenshot so it shows all of them."
                        },
                        {
                          "severity": "blocker",
                          "field": "sampleMessages",
                          "code": "samples_missing_stop",
                          "message": "Your sample messages don't tell recipients how to opt out.",
                          "suggestion": "Add opt-out language such as 'Reply STOP to unsubscribe' to your sample messages."
                        },
                        {
                          "severity": "warning",
                          "field": "sampleMessages",
                          "code": "samples_no_business_attribution",
                          "message": "Your sample messages don't mention your business name.",
                          "suggestion": "Include your business or brand name in each sample message so recipients know who is texting them."
                        },
                        {
                          "severity": "blocker",
                          "field": "entityType",
                          "code": "sole_prop_with_brn_will_be_cleared",
                          "message": "Sole proprietor submissions are sent without a registration number, so the EIN you entered would be dropped and the submission rejected.",
                          "suggestion": "If your business is registered with an EIN, set the entity type to PRIVATE_PROFIT to keep it."
                        }
                      ],
                      "proposedFixes": [
                        {
                          "field": "useCase",
                          "current": "Appointment texts",
                          "proposed": "Appointments",
                          "reason": "The closest accepted use case for your description."
                        },
                        {
                          "field": "state",
                          "current": "TX",
                          "proposed": "Texas",
                          "reason": "Use the full state or province name instead of the 2-letter code."
                        },
                        {
                          "field": "contactPhone",
                          "current": "5555550185",
                          "proposed": "+15555550185",
                          "reason": "Phone numbers need a + and the country code."
                        },
                        {
                          "field": "entityType",
                          "current": "SOLE_PROPRIETOR",
                          "proposed": "PRIVATE_PROFIT",
                          "reason": "Keeps your EIN on the submission; sole proprietor submissions are sent without one and are then rejected."
                        }
                      ]
                    }
                  },
                  "default": {
                    "summary": "A complete US candidate.",
                    "value": {
                      "verificationId": "candidate",
                      "businessName": "Contract Fixture Example LLC",
                      "country": "US",
                      "verdict": "warnings",
                      "domainAge": {
                        "domain": "example.com",
                        "registrationDate": "2026-01-01T00:00:00.000Z",
                        "ageDays": 11373,
                        "ageMonths": 373.6202365308804
                      },
                      "registry": null,
                      "issues": [
                        {
                          "severity": "warning",
                          "field": "sampleMessages",
                          "code": "samples_no_business_attribution",
                          "message": "Your sample messages don't mention your business name.",
                          "suggestion": "Include your business or brand name in each sample message so recipients know who is texting them."
                        },
                        {
                          "severity": "info",
                          "field": "_registry",
                          "code": "registry_unavailable",
                          "message": "We couldn't check your business registration automatically. This does not block your submission."
                        }
                      ],
                      "proposedFixes": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_body`: The body is a JSON array.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_body"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_body",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_body"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A JSON array instead of an object.",
                    "value": {
                      "error": "invalid_body",
                      "message": "Body must be an object."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  },
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The check failed, as when `businessName` or `doingBusinessAs` is not a string, or `state`, `contactPhone`, `website` or the registration number is a number, an object or `true`. `message` is always `Failed to run the preflight check`.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A state that is a number, which the check cannot read.",
                    "value": {
                      "error": "internal_error",
                      "message": "Failed to run the preflight check"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verify": {
      "get": {
        "operationId": "listVerifications",
        "summary": "List verifications",
        "description": "Lists the workspace's verifications, newest first: live and sandbox together for a live key, sandbox only for a test key. There is no offset or cursor: only the newest page can be read, and `has_more` is true whenever the page is full. A `pending` verification past its expiry is listed as `expired`, without being changed.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "limit-has-more",
        "x-sendly-sdk": {
          "resource": "verify",
          "method": "list"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size, 1 to 100. Defaults to 50, which is also what 0 or a value that is not a number gives. A value below 1 is raised to 1, and one above 100 is lowered to 100."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only verifications with this status. `expired` includes a `pending` one past its expiry, and `pending` leaves it out."
            },
            "required": false,
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- VerificationList: The newest verifications.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationList"
                },
                "examples": {
                  "default": {
                    "summary": "The two newest verifications.",
                    "value": {
                      "verifications": [
                        {
                          "id": "ver_placeholder3",
                          "status": "pending",
                          "phone": "+15555550100",
                          "delivery_status": "delivered",
                          "attempts": 0,
                          "max_attempts": 3,
                          "expires_at": "2026-01-01T00:00:00.000Z",
                          "verified_at": null,
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "sandbox": true,
                          "app_name": "Contract Capture",
                          "template_id": "tpl_preset_otp",
                          "profile_id": null
                        },
                        {
                          "id": "ver_placeholder2",
                          "status": "pending",
                          "phone": "+15555550100",
                          "delivery_status": "delivered",
                          "attempts": 0,
                          "max_attempts": 3,
                          "expires_at": "2026-01-01T00:00:00.000Z",
                          "verified_at": null,
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "sandbox": true,
                          "app_name": "Contract Capture",
                          "template_id": "tpl_preset_otp",
                          "profile_id": null
                        }
                      ],
                      "pagination": {
                        "limit": 2,
                        "has_more": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The verifications could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "sendVerification",
        "summary": "Send a verification code",
        "description": "Creates a verification and texts its one-time code. A test key sends nothing and returns the code in `sandbox_code`. A live key needs a verified business and charges the SMS.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:send"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "verify",
          "method": "send"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "Where to send the code, and how.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendVerificationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- Sandbox code created: A test key created the verification. No SMS was sent.\n- Code sent: A live key created the verification and the SMS was sent.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SandboxVerificationResult"
                    },
                    {
                      "$ref": "#/components/schemas/LiveVerificationResult"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key's code, created in the sandbox: no SMS is sent.",
                    "value": {
                      "id": "ver_placeholder2",
                      "status": "pending",
                      "phone": "+15555550100",
                      "expires_at": "2026-01-01T00:00:00.000Z",
                      "sandbox": true,
                      "sandbox_code": "394326",
                      "message": "Sandbox mode: SMS not sent. Use the sandbox_code to verify."
                    }
                  },
                  "live": {
                    "summary": "A live key's code, sent by SMS. Built from the handler code, not captured: it needs a live key and texts a real phone.",
                    "value": {
                      "id": "ver_placeholder101",
                      "status": "pending",
                      "phone": "+15555550100",
                      "expires_at": "2026-01-01T00:00:00.000Z",
                      "sandbox": false
                    }
                  },
                  "short-timeout": {
                    "summary": "A test key's code that expires after 60 seconds.",
                    "value": {
                      "id": "ver_placeholder3",
                      "status": "pending",
                      "phone": "+15555550100",
                      "expires_at": "2026-01-01T00:00:00.000Z",
                      "sandbox": true,
                      "sandbox_code": "333238",
                      "message": "Sandbox mode: SMS not sent. Use the sandbox_code to verify."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `channel_not_supported`: `channel` is set to anything but `sms`.\n- `invalid_request`: `to` is missing or not a string, `profile_id` names no profile of this workspace, `template_id` names no template, or the template is neither a preset nor published.\n- `invalid_phone_format`: `to` is not a valid phone number.\n- `compliance_blocked`: The message, with the code left out, has restricted (SHAFT) content.\n- `unsupported_destination`: A live key's destination has no OTP price, or its country is not supported.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "channel_not_supported"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "channel_not_supported",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "channel_not_supported"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_phone_format"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_phone_format",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_phone_format"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SHAFT_CONTENT_DETECTED"
                          ]
                        },
                        "category": {
                          "type": "string",
                          "description": "The restricted category the text matched. Known values: `sex`, `hate`, `alcohol`, `firearms`, `tobacco`, `cannabis`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "sex",
                            "hate",
                            "alcohol",
                            "firearms",
                            "tobacco",
                            "cannabis"
                          ]
                        },
                        "matchedTerms": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "category",
                        "matchedTerms"
                      ],
                      "title": "compliance_blocked: SHAFT content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "unsupported_destination"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "country": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The destination's country code, when known. Absent when the destination has no OTP price."
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "unsupported_destination",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "unsupported_destination"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-phone": {
                    "summary": "A phone number that is not valid.",
                    "value": {
                      "error": "invalid_phone_format",
                      "message": "Invalid phone number. Use E.164 format (e.g., +15555550101)"
                    }
                  },
                  "default": {
                    "summary": "The phone number is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Phone number (to) is required"
                    }
                  },
                  "whatsapp-channel": {
                    "summary": "A code asked for over WhatsApp.",
                    "value": {
                      "error": "channel_not_supported",
                      "message": "Verification over WhatsApp is not yet available. Omit \"channel\" to deliver the code via SMS."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: A live key's balance does not cover the SMS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "insufficient_credits"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "creditsNeeded": {
                      "type": "integer"
                    },
                    "currentBalance": {
                      "type": "integer"
                    },
                    "tier": {
                      "type": "string",
                      "description": "The destination's price tier. Known values: `domestic`, `tier1`, `tier2`, `tier3`, `tier4`, `tier5`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "domestic",
                        "tier1",
                        "tier2",
                        "tier3",
                        "tier4",
                        "tier5"
                      ]
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "creditsNeeded",
                    "currentBalance",
                    "tier"
                  ],
                  "title": "insufficient_credits, with the tier",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "insufficient_credits"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `verification_required`: A live key's business is not verified, or it has no active send authorization.\n- `registration_required`: A live key's destination country needs a registered sender ID first.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "verification_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "verification_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "verification_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "registration_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SENDER_ID_NOT_REGISTERED"
                          ]
                        },
                        "countryCode": {
                          "type": "string"
                        },
                        "countryName": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "countryCode",
                        "countryName"
                      ],
                      "title": "registration_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "registration_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `destination_not_allowed`: The profile's `allowed_countries` leaves out the destination.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "destination_not_allowed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "country": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The destination's country code, when known."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "country"
                      ],
                      "title": "destination_not_allowed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "destination_not_allowed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "idempotency-key-mismatch": {
                    "summary": "The first code's Idempotency-Key, reused with a different body.",
                    "value": {
                      "error": "idempotency_key_mismatch",
                      "message": "This idempotency key was already used with a different request body. Use a new key for different requests."
                    }
                  },
                  "default": {
                    "summary": "A profile that allows Great Britain only, for a US number.",
                    "value": {
                      "error": "destination_not_allowed",
                      "message": "This verify profile does not allow sending to the destination country",
                      "country": "US"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `rate_limit_exceeded`: The phone number already had 5 codes in the last 10 minutes or 20 in the last day from this workspace owner's workspaces in this mode (test or live, counted apart), or 15 in the last 10 minutes or 60 in the last day from every account's live sends together, or the account sent 100 codes in the last minute. `retryAfter` is in seconds.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `configuration_error`: A live key's account has no messaging profile.\n- `delivery_failed`: The SMS could not be sent. The verification is marked failed and nothing is charged. `message` is the sender's own error text.\n- `internal_error`: The verification could not be created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "configuration_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "configuration_error",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "configuration_error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "delivery_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "delivery_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "delivery_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verify/profiles": {
      "get": {
        "operationId": "listVerifyProfiles",
        "summary": "List verify profiles",
        "description": "Lists every verify profile of the workspace, newest first, with no paging.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- VerifyProfileList: Every profile.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyProfileList"
                },
                "examples": {
                  "default": {
                    "summary": "The workspace's profiles.",
                    "value": {
                      "profiles": [
                        {
                          "id": "vp_placeholder1",
                          "name": "contract-capture-00000000-0000-4000-8000-000000000001",
                          "template_id": null,
                          "app_name": "Contract Capture",
                          "default_timeout_secs": 600,
                          "code_length": 6,
                          "max_attempts": 3,
                          "allowed_countries": [
                            "GB"
                          ],
                          "webhook_url": "https://example.com/verify-webhook",
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "updated_at": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The profiles could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createVerifyProfile",
        "summary": "Create a verify profile",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The profile.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVerifyProfileRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- VerifyProfile: The profile was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyProfile"
                },
                "examples": {
                  "default": {
                    "summary": "A profile that allows codes to Great Britain only.",
                    "value": {
                      "id": "vp_placeholder1",
                      "name": "contract-capture-00000000-0000-4000-8000-000000000001",
                      "template_id": null,
                      "app_name": "Contract Capture",
                      "default_timeout_secs": 600,
                      "code_length": 6,
                      "max_attempts": 3,
                      "allowed_countries": [
                        "GB"
                      ],
                      "webhook_url": "https://example.com/verify-webhook",
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `name` is missing or blank, `template_id` names nothing this workspace can use, a number is out of range, or `webhook_url` is not `https://`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The name is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Profile name is required"
                    }
                  },
                  "timeout-out-of-range": {
                    "summary": "A default timeout under 60 seconds.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Timeout must be between 60 and 3600 seconds"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The profile could not be created, including when `webhook_url` or `allowed_countries` has the wrong type, or a number field is not a whole number.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verify/profiles/{id}": {
      "get": {
        "operationId": "getVerifyProfile",
        "summary": "Get a verify profile",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The profile's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- VerifyProfile: The profile.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyProfile"
                },
                "examples": {
                  "default": {
                    "summary": "The profile the capture created.",
                    "value": {
                      "id": "vp_placeholder1",
                      "name": "contract-capture-00000000-0000-4000-8000-000000000001",
                      "template_id": null,
                      "app_name": "Contract Capture",
                      "default_timeout_secs": 600,
                      "code_length": 6,
                      "max_attempts": 3,
                      "allowed_countries": [
                        "GB"
                      ],
                      "webhook_url": "https://example.com/verify-webhook",
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No profile with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no profile.",
                    "value": {
                      "error": "not_found",
                      "message": "Verify profile not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The profile could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateVerifyProfile",
        "summary": "Update a verify profile",
        "description": "Changes the fields sent and leaves the others alone.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The profile's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateVerifyProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- VerifyProfile: The changed profile.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyProfile"
                },
                "examples": {
                  "default": {
                    "summary": "Renamed, with five attempts.",
                    "value": {
                      "id": "vp_placeholder1",
                      "name": "contract-capture-00000000-0000-4000-8000-000000000002",
                      "template_id": null,
                      "app_name": "Contract Capture",
                      "default_timeout_secs": 600,
                      "code_length": 6,
                      "max_attempts": 5,
                      "allowed_countries": [
                        "GB"
                      ],
                      "webhook_url": "https://example.com/verify-webhook",
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: No field to change was sent, `name` is blank or not a string, `template_id` names nothing this workspace can use, a number is out of range, or `webhook_url` is not `https://`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No field to change.",
                    "value": {
                      "error": "invalid_request",
                      "message": "No valid updates provided"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No profile with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no profile.",
                    "value": {
                      "error": "not_found",
                      "message": "Verify profile not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The profile could not be changed, including when `webhook_url` or `allowed_countries` has the wrong type, or a number field is not a whole number.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteVerifyProfile",
        "summary": "Delete a verify profile",
        "description": "Deletes the profile. Verifications sent with it keep their settings, and their `profile_id` becomes `null`.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The profile's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.\n\n- The profile was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No profile with this id belongs to the key's workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "The same profile again, now deleted.",
                    "value": {
                      "error": "not_found",
                      "message": "Verify profile not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The profile could not be deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verify/sessions": {
      "post": {
        "operationId": "createVerifySession",
        "summary": "Create a hosted verification session",
        "description": "Creates a hosted page where the user enters a phone number and the code sent to it. When they finish, the page sends them to `success_url` with a token to validate.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "verify.sessions",
          "method": "create"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "Where to send the user, and how the page looks.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVerifySessionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- VerifySession: The session was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifySession"
                },
                "examples": {
                  "default": {
                    "summary": "A hosted session with its own branding and metadata.",
                    "value": {
                      "id": "ses_placeholder4",
                      "url": "https://sendly.live/v/ses_placeholder4",
                      "status": "pending",
                      "success_url": "https://example.com/verified",
                      "cancel_url": "https://example.com/cancelled",
                      "brand_name": "Example",
                      "brand_color": "#f59e0b",
                      "metadata": {
                        "orderId": "A-100"
                      },
                      "expires_at": "2026-01-01T00:00:00.000Z",
                      "created_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `success_url` is missing, a URL is not `https://` (or localhost), `brand_color` is not a hex color, or `border_radius` or `font_family` is not one of its values.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "success_url is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "success_url is required"
                    }
                  },
                  "not-https": {
                    "summary": "An http success_url that is not localhost.",
                    "value": {
                      "error": "invalid_request",
                      "message": "success_url must be a valid HTTPS URL (localhost allowed for dev)"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The session could not be created. `message` is the error's own text, which can be a database error.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verify/sessions/validate": {
      "post": {
        "operationId": "validateVerifySession",
        "summary": "Validate a hosted session token",
        "description": "Confirms the token from a finished hosted session and returns the verified phone number. A token validates once.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "verify.sessions",
          "method": "validate"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The token to validate.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidateSessionTokenRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- ValidateSessionTokenResult: The token is valid, and is now used.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateSessionTokenResult"
                },
                "examples": {
                  "default": {
                    "summary": "The token of a hosted session the test key's sandbox verified, with the code it returned.",
                    "value": {
                      "valid": true,
                      "phone": "+15555550100",
                      "verified_at": "2026-01-01T00:00:00.000Z",
                      "metadata": {
                        "orderId": "A-100"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `token` is missing.\n- `invalid_token`, `token_already_used`, `not_verified`: The token is unknown (`invalid_token`), belongs to another API key (`invalid_token`), was already validated (`token_already_used`), or its session is not verified (`not_verified`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_token",
                            "token_already_used",
                            "not_verified"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "valid": {
                          "type": "boolean",
                          "enum": [
                            false
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "valid"
                      ],
                      "title": "Token refused",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_token",
                        "token_already_used",
                        "not_verified"
                      ]
                    }
                  ]
                },
                "examples": {
                  "already-used": {
                    "summary": "The same token again.",
                    "value": {
                      "error": "token_already_used",
                      "message": "This token has already been validated",
                      "valid": false
                    }
                  },
                  "default": {
                    "summary": "A token that matches no session.",
                    "value": {
                      "error": "invalid_token",
                      "message": "Invalid or expired token",
                      "valid": false
                    }
                  },
                  "missing-token": {
                    "summary": "No token.",
                    "value": {
                      "error": "invalid_request",
                      "message": "token is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The token could not be validated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verify/{id}": {
      "get": {
        "operationId": "getVerification",
        "summary": "Get a verification",
        "description": "Returns one verification of this workspace. A `pending` one past its expiry is marked `expired` first. A test key reads only verifications a test key created.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "verify",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The verification's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Verification: The verification.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                },
                "examples": {
                  "default": {
                    "summary": "The test key's pending verification.",
                    "value": {
                      "id": "ver_placeholder2",
                      "status": "pending",
                      "phone": "+15555550100",
                      "delivery_status": "delivered",
                      "attempts": 0,
                      "max_attempts": 3,
                      "expires_at": "2026-01-01T00:00:00.000Z",
                      "verified_at": null,
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "sandbox": true,
                      "app_name": "Contract Capture",
                      "template_id": "tpl_preset_otp",
                      "profile_id": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No verification with this id belongs to the key's workspace, or it is live and a test key asked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no verification.",
                    "value": {
                      "error": "not_found",
                      "message": "Verification not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The verification could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verify/{id}/check": {
      "post": {
        "operationId": "checkVerification",
        "summary": "Check a verification code",
        "description": "Checks the code the user entered. Each wrong code uses an attempt. The right code verifies it; checking the same right code again answers the same way. A test key checks only a verification a test key created, and a live key only a live one.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "verify",
          "method": "check"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The verification's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The code to check.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckVerificationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- CheckVerificationResult: The code is right, now or when the verification was first verified.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckVerificationResult"
                },
                "examples": {
                  "already-verified": {
                    "summary": "The right code again, after it verified.",
                    "value": {
                      "id": "ver_placeholder2",
                      "status": "verified",
                      "phone": "+15555550100",
                      "verified_at": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "default": {
                    "summary": "The right code.",
                    "value": {
                      "id": "ver_placeholder2",
                      "status": "verified",
                      "phone": "+15555550100",
                      "verified_at": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `code` is missing or not a string.\n- `invalid_code`: The code is wrong. Attempts remain, or the verification was already verified with another code.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_code"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "remaining_attempts": {
                          "type": "integer",
                          "description": "How many more codes may be checked. Absent when the verification was already verified."
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_code",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_code"
                      ]
                    }
                  ]
                },
                "examples": {
                  "already-verified-wrong-code": {
                    "summary": "A wrong code, after the verification was verified.",
                    "value": {
                      "error": "invalid_code",
                      "message": "Invalid verification code"
                    }
                  },
                  "default": {
                    "summary": "A wrong code, with attempts left.",
                    "value": {
                      "error": "invalid_code",
                      "message": "Invalid verification code",
                      "remaining_attempts": 2
                    }
                  },
                  "missing-code": {
                    "summary": "No code.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Verification code is required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No verification with this id belongs to the key's workspace, or it was created in the other mode: live for a test key, sandbox for a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no verification.",
                    "value": {
                      "error": "not_found",
                      "message": "Verification not found"
                    }
                  }
                }
              }
            }
          },
          "410": {
            "description": "HTTP 410.\n\n- `expired`: The code expired. The verification is marked expired.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "expired"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "expired",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "expired"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A code checked after the verification expired.",
                    "value": {
                      "error": "expired",
                      "message": "Verification code has expired"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `max_attempts_exceeded`: Every attempt was used, or this wrong code used the last one. The verification is marked failed.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "max_attempts_exceeded"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "max_attempts_exceeded",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "max_attempts_exceeded"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A third wrong code, which uses the last attempt.",
                    "value": {
                      "error": "max_attempts_exceeded",
                      "message": "Maximum verification attempts exceeded"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The code could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/verify/{id}/resend": {
      "post": {
        "operationId": "resendVerification",
        "summary": "Resend a verification code",
        "description": "Sends a new code for an expired verification, or a pending one whose SMS failed, and resets its attempts and expiry. A test key resends only a verification a test key created, sends nothing and returns the code in `sandbox_code`; a live key resends only a live one.",
        "tags": [
          "Verification and OTP"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "verify:send"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "verify",
          "method": "resend"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The verification's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Sandbox code created: A test key made a new code. No SMS was sent.\n- New code sent: A live key sent a new code.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SandboxVerificationResult"
                    },
                    {
                      "$ref": "#/components/schemas/LiveResendResult"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A new sandbox code for an expired verification.",
                    "value": {
                      "id": "ver_placeholder3",
                      "status": "pending",
                      "phone": "+15555550100",
                      "expires_at": "2026-01-01T00:00:00.000Z",
                      "sandbox": true,
                      "sandbox_code": "201912",
                      "message": "Sandbox mode: OTP resent. Use the sandbox_code to verify."
                    }
                  },
                  "live": {
                    "summary": "A new code for an expired verification, sent by SMS with a live key. Built from the handler code, not captured: it needs a live key and texts a real phone.",
                    "value": {
                      "id": "ver_placeholder101",
                      "status": "pending",
                      "phone": "+15555550100",
                      "expires_at": "2026-01-01T00:00:00.000Z",
                      "sandbox": false,
                      "message": "OTP resent successfully"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_state`: The verification is not expired, and not pending with a failed SMS. `message` names its status and delivery status.\n- `compliance_blocked`: The message, with the code left out, has restricted (SHAFT) content.\n- `unsupported_destination`: A live key's destination country is not supported.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_state"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_state",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_state"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SHAFT_CONTENT_DETECTED"
                          ]
                        },
                        "category": {
                          "type": "string",
                          "description": "The restricted category the text matched. Known values: `sex`, `hate`, `alcohol`, `firearms`, `tobacco`, `cannabis`. More can be added at any time, so treat an unknown value as valid.",
                          "x-sendly-extensible-enum": [
                            "sex",
                            "hate",
                            "alcohol",
                            "firearms",
                            "tobacco",
                            "cannabis"
                          ]
                        },
                        "matchedTerms": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "category",
                        "matchedTerms"
                      ],
                      "title": "compliance_blocked: SHAFT content",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "compliance_blocked"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "unsupported_destination"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "country": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The destination's country code, when known. Absent when the destination has no OTP price."
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "unsupported_destination",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "unsupported_destination"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A verification that was already verified.",
                    "value": {
                      "error": "invalid_state",
                      "message": "Cannot resend verification in verified state with delivery status delivered"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `insufficient_credits`: A live key's balance does not cover the SMS.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InsufficientCreditsError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (verify:send), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `registration_required`: A live key's destination country needs a registered sender ID first.\n- `verification_required`: A live key's account has no active send authorization.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "registration_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "SENDER_ID_NOT_REGISTERED"
                          ]
                        },
                        "countryCode": {
                          "type": "string"
                        },
                        "countryName": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "code",
                        "countryCode",
                        "countryName"
                      ],
                      "title": "registration_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "registration_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "verification_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "verification_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "verification_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No verification with this id belongs to the key's workspace, or it was created in the other mode: live for a test key, sandbox for a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no verification.",
                    "value": {
                      "error": "not_found",
                      "message": "Verification not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `destination_not_allowed`: The verification's profile no longer allows the destination country.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "destination_not_allowed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "country": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The destination's country code, when known."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "country"
                  ],
                  "title": "destination_not_allowed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "destination_not_allowed"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.\n- `rate_limit_exceeded`: The phone number already had 5 codes in the last 10 minutes or 20 in the last day from this workspace owner's workspaces in this mode (test or live, counted apart), or 15 in the last 10 minutes or 60 in the last day from every account's live sends together, or the account sent 100 codes in the last minute. `retryAfter` is in seconds.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `configuration_error`: The verification's template no longer exists, or a live key's account has no messaging profile.\n- `delivery_failed`: The SMS could not be sent. Nothing is charged. `message` is the sender's own error text.\n- `internal_error`: The code could not be resent.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "configuration_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "configuration_error",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "configuration_error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "delivery_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "delivery_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "delivery_failed"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voice/agents": {
      "get": {
        "operationId": "listVoiceAgents",
        "summary": "List voice agents",
        "description": "Lists the workspace's AI agents, oldest first, with how many calls each has handled. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.agents",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- VoiceAgentList: Every agent in the workspace, with no paging.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceAgentList"
                },
                "examples": {
                  "default": {
                    "summary": "The workspace's agents: none yet.",
                    "value": {
                      "data": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:read` permission for calls and voice.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Reading the agents failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createVoiceAgent",
        "summary": "Create a voice agent",
        "description": "Creates an AI agent and issues it a live `sms:send` key of its own, so that it can text callers. A workspace has at most 20 agents. Needs a live key. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.agents",
          "method": "create"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The agent to create. Only `name` is required.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVoiceAgentRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- VoiceAgent: The agent was created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceAgent"
                },
                "examples": {
                  "default": {
                    "summary": "A new agent, with its own sending key. Built from the handler and serializer code, not captured: a test key cannot reach this response. `tools.backgroundAudio`, which main's #211 (a43a32a3) added, is the default `false`.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "object": "voice_agent",
                      "name": "Front desk",
                      "enabled": true,
                      "voice": "ashley",
                      "voiceLabel": "Ashley (US, warm)",
                      "language": "en-US",
                      "greeting": "Thanks for calling, how can I help?",
                      "instructions": "Answer questions about opening hours, and offer to text the address.",
                      "tools": {
                        "sendSms": true,
                        "transferTo": null,
                        "backgroundAudio": false
                      },
                      "canSendSms": true,
                      "callsHandled": 0,
                      "avgDurationSecs": 0,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_request`: The body is not a JSON object, or a field is missing, of the wrong type or too long. `message` names the first such field, as in `name is required.`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `api_keys:write` permission for calls and voice.\n- `live_key_required`: A test key or a CLI session called it. Calls and voice changes need a live API key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "live-key-required": {
                    "summary": "A test key asked to create an agent, which needs a live key.",
                    "value": {
                      "error": "live_key_required",
                      "message": "Phone calls need a live API key."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNotEnabledError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `agent_limit`: The workspace already has 20 agents.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "agent_limit"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "agent_limit",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "agent_limit"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Creating the agent failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voice/agents/{id}": {
      "get": {
        "operationId": "getVoiceAgent",
        "summary": "Get a voice agent",
        "description": "Returns one of the workspace's AI agents. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.agents",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The agent's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- VoiceAgent: The agent.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceAgent"
                },
                "examples": {
                  "default": {
                    "summary": "An agent that has handled calls. Built from the handler and serializer code, not captured: the test workspace has no agent, and a test key cannot create one. `tools.backgroundAudio`, which main's #211 (a43a32a3) added, is the default `false`.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "object": "voice_agent",
                      "name": "Front desk",
                      "enabled": true,
                      "voice": "ashley",
                      "voiceLabel": "Ashley (US, warm)",
                      "language": "en-US",
                      "greeting": "Thanks for calling, how can I help?",
                      "instructions": "Answer questions about opening hours, and offer to text the address.",
                      "tools": {
                        "sendSms": true,
                        "transferTo": null,
                        "backgroundAudio": false
                      },
                      "canSendSms": true,
                      "callsHandled": 12,
                      "avgDurationSecs": 94,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:read` permission for calls and voice.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `agent_not_found`: No agent with this id is in the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "agent_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "agent_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "agent_not_found"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no agent in the workspace.",
                    "value": {
                      "error": "agent_not_found",
                      "message": "That agent doesn't exist in this workspace."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Reading the agent failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateVoiceAgent",
        "summary": "Update a voice agent",
        "description": "Changes the fields sent and leaves the rest. `tools` is merged into the agent's tools. Changing `voice` without `language` moves the language to the new voice's when the old one does not suit it. An agent without a sending key is issued one. Needs a live key. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.agents",
          "method": "update"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The agent's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateVoiceAgentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- VoiceAgent: The updated agent.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceAgent"
                },
                "examples": {
                  "default": {
                    "summary": "A new voice, without a language: the agent moves to the voice's language. Built from the handler and serializer code, not captured: a test key cannot reach this response. `tools.backgroundAudio`, which main's #211 (a43a32a3) added, is the default `false`.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "object": "voice_agent",
                      "name": "Front desk",
                      "enabled": true,
                      "voice": "diego",
                      "voiceLabel": "Diego (Spanish, MX)",
                      "language": "es-MX",
                      "greeting": "Thanks for calling, how can I help?",
                      "instructions": "Answer questions about opening hours, and offer to text the address.",
                      "tools": {
                        "sendSms": true,
                        "transferTo": null,
                        "backgroundAudio": false
                      },
                      "canSendSms": true,
                      "callsHandled": 12,
                      "avgDurationSecs": 94,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-02T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_request`: The body is not a JSON object, or a field is of the wrong type or too long. Checked before the agent is looked up.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `api_keys:write` permission for calls and voice.\n- `live_key_required`: A test key or a CLI session called it. Calls and voice changes need a live API key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "live-key-required": {
                    "summary": "A test key asked to change an agent, which needs a live key.",
                    "value": {
                      "error": "live_key_required",
                      "message": "Phone calls need a live API key."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `agent_not_found`: No agent with this id is in the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "agent_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "agent_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "agent_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `agent_in_use`: `enabled` is `false` while numbers still send their calls to the agent. `numbers` lists them.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "agent_in_use"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "numbers": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "description": "A number the agent answers."
                      },
                      "description": "The numbers that still send their calls to the agent, in E.164 format."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "numbers"
                  ],
                  "title": "agent_in_use",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "agent_in_use"
                  ]
                },
                "examples": {
                  "agent-in-use": {
                    "summary": "Switching off an agent that still answers a number. Built from the handler and serializer code, not captured: a test key cannot reach this response.",
                    "value": {
                      "error": "agent_in_use",
                      "message": "This agent answers 1 number. Point it elsewhere first.",
                      "numbers": [
                        "+15555550110"
                      ]
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Updating the agent failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteVoiceAgent",
        "summary": "Delete a voice agent",
        "description": "Revokes the agent's sending key, then removes the agent. Needs a live key. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.agents",
          "method": "delete"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The agent's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- DeletedVoiceAgent: The agent was removed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedVoiceAgent"
                },
                "examples": {
                  "default": {
                    "summary": "The agent was removed and its sending key revoked. Built from the handler and serializer code, not captured: a test key cannot reach this response.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "object": "voice_agent",
                      "deleted": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `api_keys:write` permission for calls and voice.\n- `live_key_required`: A test key or a CLI session called it. Calls and voice changes need a live API key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "live-key-required": {
                    "summary": "A test key asked to remove an agent, which needs a live key.",
                    "value": {
                      "error": "live_key_required",
                      "message": "Phone calls need a live API key."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `agent_not_found`: No agent with this id is in the workspace, or it was already removed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "agent_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "agent_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "agent_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `agent_in_use`: Numbers still send their calls to the agent. `numbers` lists them; point them elsewhere first.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "agent_in_use"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "numbers": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "description": "A number the agent answers."
                      },
                      "description": "The numbers that still send their calls to the agent, in E.164 format."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "numbers"
                  ],
                  "title": "agent_in_use",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "agent_in_use"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Removing the agent, or revoking its key, failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voice/numbers": {
      "get": {
        "operationId": "listVoiceNumbers",
        "summary": "List voice numbers",
        "description": "Lists the workspace's active phone numbers, the default first and then oldest first, with how each handles calls. Every active number can carry voice. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.numbers",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- VoiceNumberList: Every active number in the workspace, with no paging.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNumberList"
                },
                "examples": {
                  "default": {
                    "summary": "The workspace's active numbers.",
                    "value": {
                      "data": [
                        {
                          "id": "00000000-0000-4000-8000-000000000001",
                          "object": "voice_number",
                          "phoneNumber": "+15555550100",
                          "phoneNumberType": "local",
                          "countryCode": "CA",
                          "isDefault": true,
                          "voiceEnabled": false,
                          "voiceMode": "none",
                          "agentId": null,
                          "emergencyAddress": null,
                          "ratePerMinute": {
                            "inbound": 2,
                            "outbound": 2,
                            "agent": 10
                          }
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "object": "voice_number",
                          "phoneNumber": "+15555550101",
                          "phoneNumberType": "mobile",
                          "countryCode": "GB",
                          "isDefault": false,
                          "voiceEnabled": false,
                          "voiceMode": "none",
                          "agentId": null,
                          "emergencyAddress": null,
                          "ratePerMinute": {
                            "inbound": 2,
                            "outbound": 2,
                            "agent": 10
                          }
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000003",
                          "object": "voice_number",
                          "phoneNumber": "+15555550102",
                          "phoneNumberType": "toll_free",
                          "countryCode": null,
                          "isDefault": false,
                          "voiceEnabled": true,
                          "voiceMode": "ring_dashboard",
                          "agentId": null,
                          "emergencyAddress": null,
                          "ratePerMinute": {
                            "inbound": 3,
                            "outbound": 2,
                            "agent": 11
                          }
                        },
                        {
                          "id": "00000000-0000-4000-8000-000000000004",
                          "object": "voice_number",
                          "phoneNumber": "+15555550103",
                          "phoneNumberType": "local",
                          "countryCode": null,
                          "isDefault": false,
                          "voiceEnabled": true,
                          "voiceMode": "ring_dashboard",
                          "agentId": null,
                          "emergencyAddress": null,
                          "ratePerMinute": {
                            "inbound": 2,
                            "outbound": 2,
                            "agent": 10
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:read` permission for calls and voice.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Reading the numbers failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voice/numbers/{number}": {
      "get": {
        "operationId": "getVoiceNumber",
        "summary": "Get a voice number",
        "description": "Returns one of the workspace's active numbers, by id or by phone number. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.numbers",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The number's id, or the phone number in E.164 format with its leading `+` (URL-encoded as `%2B` or sent as is)."
            },
            "required": true,
            "name": "number",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- VoiceNumber: The number.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNumber"
                },
                "examples": {
                  "by-phone-number": {
                    "summary": "The same number, by its phone number.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "object": "voice_number",
                      "phoneNumber": "+15555550100",
                      "phoneNumberType": "local",
                      "countryCode": "CA",
                      "isDefault": true,
                      "voiceEnabled": false,
                      "voiceMode": "none",
                      "agentId": null,
                      "emergencyAddress": null,
                      "ratePerMinute": {
                        "inbound": 2,
                        "outbound": 2,
                        "agent": 10
                      }
                    }
                  },
                  "default": {
                    "summary": "A number, by its id.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "object": "voice_number",
                      "phoneNumber": "+15555550100",
                      "phoneNumberType": "local",
                      "countryCode": "CA",
                      "isDefault": true,
                      "voiceEnabled": false,
                      "voiceMode": "none",
                      "agentId": null,
                      "emergencyAddress": null,
                      "ratePerMinute": {
                        "inbound": 2,
                        "outbound": 2,
                        "agent": 10
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:read` permission for calls and voice.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `number_not_found`: No active number with this id or phone number is in the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_not_found"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no active number in the workspace.",
                    "value": {
                      "error": "number_not_found",
                      "message": "This number isn't in your workspace."
                    }
                  },
                  "unknown-phone-number": {
                    "summary": "A phone number the workspace does not have.",
                    "value": {
                      "error": "number_not_found",
                      "message": "This number isn't in your workspace."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Reading the number failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateVoiceNumber",
        "summary": "Update a number's voice settings",
        "description": "Switches calls on or off for a number and chooses how it answers. Switching voice on routes the number to the voice network first, so a number never claims calls it cannot take. Needs a live key. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.numbers",
          "method": "update"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The number's id, or the phone number in E.164 format with its leading `+` (URL-encoded as `%2B` or sent as is)."
            },
            "required": true,
            "name": "number",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The settings to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateVoiceNumberRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- VoiceNumber: The number with its new settings.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNumber"
                },
                "examples": {
                  "default": {
                    "summary": "The number now answers with an agent. Built from the handler and serializer code, not captured: a test key cannot reach this response.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000102",
                      "object": "voice_number",
                      "phoneNumber": "+15555550110",
                      "phoneNumberType": "local",
                      "countryCode": "US",
                      "isDefault": true,
                      "voiceEnabled": true,
                      "voiceMode": "agent",
                      "agentId": "00000000-0000-4000-8000-000000000101",
                      "emergencyAddress": null,
                      "ratePerMinute": {
                        "inbound": 2,
                        "outbound": 2,
                        "agent": 10
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_request`: The body is not a JSON object, `voiceEnabled` is not a boolean, or `agentId` is neither a string nor `null`. Checked before the number is looked up.\n- `invalid_voice_mode`: `voiceMode` is not `none`, `ring_dashboard` or `agent`.\n- `agent_required`: The number would answer with an agent, but no agent is set.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_voice_mode"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_voice_mode",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_voice_mode"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "agent_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "agent_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "agent_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `settings:write` permission for calls and voice.\n- `live_key_required`: A test key or a CLI session called it. Calls and voice changes need a live API key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "live-key-required": {
                    "summary": "A test key asked to change a number's voice settings, which needs a live key.",
                    "value": {
                      "error": "live_key_required",
                      "message": "Phone calls need a live API key."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `number_not_found`: No active number with this id or phone number is in the workspace.\n- `agent_not_found`: The agent the number would answer with is not in the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_not_found"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "agent_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "agent_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "agent_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `agent_disabled`: The agent the number would answer with is switched off.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "agent_disabled"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "agent_disabled",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "agent_disabled"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Saving the settings failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `voice_attach_failed`: Switching voice on: the carrier network or the voice network refused the change.\n- `voice_unavailable`: Switching voice on, while the voice network connection is not configured.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "voice_attach_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "voice_attach_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "voice_attach_failed"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "voice_unavailable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "voice_unavailable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "voice_unavailable"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voice/numbers/{number}/emergency-address": {
      "post": {
        "operationId": "registerVoiceNumberEmergencyAddress",
        "summary": "Register a number's emergency address",
        "description": "Checks the address, registers it for emergency (E911) calling on the number, and the first time adds the emergency service's monthly charge to the number's monthly cost. US and Canadian numbers only. Needs a live key. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.numbers",
          "method": "registerEmergencyAddress"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The number's id, or the phone number in E.164 format with its leading `+` (URL-encoded as `%2B` or sent as is)."
            },
            "required": true,
            "name": "number",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The address emergency services are sent to.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterEmergencyAddressRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- VoiceNumber: The number, with `emergencyAddress` set.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNumber"
                },
                "examples": {
                  "default": {
                    "summary": "The address was accepted and the registration is under way. Built from the handler and serializer code, not captured: a test key cannot reach this response.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000102",
                      "object": "voice_number",
                      "phoneNumber": "+15555550110",
                      "phoneNumberType": "local",
                      "countryCode": "US",
                      "isDefault": true,
                      "voiceEnabled": true,
                      "voiceMode": "ring_dashboard",
                      "agentId": null,
                      "emergencyAddress": {
                        "status": "provisioning",
                        "address": {
                          "street": "100 Example Street",
                          "city": "Austin",
                          "state": "TX",
                          "zip": "78701",
                          "country": "US"
                        }
                      },
                      "ratePerMinute": {
                        "inbound": 2,
                        "outbound": 2,
                        "agent": 10
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_request`: The body is not a JSON object, or an address field is neither a string nor `null`.\n- `invalid_address`: The address is incomplete or malformed: a required field is missing, `country` is not `US` or `CA`, `state` is not two letters, or the ZIP or postal code does not fit the country. Checked before the number is looked up.\n- `e911_not_applicable`: The number is not a US or Canadian number, or it is toll-free: a toll-free number cannot hold an emergency address, so it receives calls but cannot place them.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_address"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_address",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_address"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "e911_not_applicable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "e911_not_applicable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "e911_not_applicable"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `settings:write` permission for calls and voice.\n- `live_key_required`: A test key or a CLI session called it. Calls and voice changes need a live API key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "live-key-required": {
                    "summary": "A test key asked to register an emergency address, which needs a live key.",
                    "value": {
                      "error": "live_key_required",
                      "message": "Phone calls need a live API key."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.\n- `number_not_found`: No active number with this id or phone number is in the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/VoiceNotEnabledError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `invalid_address`: The address check did not confirm the address or could not be reached, the phone network refused the address as entered, or neither the workspace nor the account has a name to register it under. `suggested` holds the check's correction, when it made one.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_address"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggested": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "properties": {
                            "street": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "unit": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "city": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "state": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "zip": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "country": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "description": "A correction to offer the user, or `null` when the check proposed none."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "suggested"
                      ],
                      "title": "invalid_address",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_address"
                      ]
                    }
                  ]
                },
                "examples": {
                  "address-not-verified": {
                    "summary": "The address check did not confirm the address, and proposed a correction. Built from the handler and serializer code, not captured: a test key cannot reach this response.",
                    "value": {
                      "error": "invalid_address",
                      "message": "That address couldn't be verified for emergency services. Check the street, city, state and ZIP.",
                      "suggested": {
                        "street": "100 EXAMPLE ST",
                        "city": "AUSTIN",
                        "state": "TX",
                        "zip": "78701-1234",
                        "country": "US"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Registering the address failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `carrier_refused`: The address could not be created, the number could not be found, or emergency calling could not be switched on, on the carrier network.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "carrier_refused"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "suggested": {
                      "type": "null",
                      "description": "Always `null`."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "suggested"
                  ],
                  "title": "carrier_refused",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "carrier_refused"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voice/voices": {
      "get": {
        "operationId": "listVoices",
        "summary": "List voices",
        "description": "Lists the voices an agent can speak with. Behind the `voice_channel` flag for the key's owner, or the workspace's `voice` feature: until one is on, every Voice operation answers 404 `voice_not_enabled`.",
        "tags": [
          "Voice"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "calls:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "voice.voices",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- VoicePresetList: Every voice, with no paging.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoicePresetList"
                },
                "examples": {
                  "default": {
                    "summary": "Every voice an agent can speak with.",
                    "value": {
                      "data": [
                        {
                          "id": "ashley",
                          "label": "Ashley (US, warm)",
                          "language": "en"
                        },
                        {
                          "id": "edward",
                          "label": "Edward (US, calm)",
                          "language": "en"
                        },
                        {
                          "id": "olivia",
                          "label": "Olivia (UK, bright)",
                          "language": "en"
                        },
                        {
                          "id": "jacqueline",
                          "label": "Jacqueline (US, natural)",
                          "language": "en"
                        },
                        {
                          "id": "diego",
                          "label": "Diego (Spanish, MX)",
                          "language": "es"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "no-authorization": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (calls:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `forbidden`: In a team workspace, the caller's role lacks the `calls:read` permission for calls and voice.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `voice_not_enabled`: Voice is not enabled for the account.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `voice_internal_error`: The account's Voice access could not be checked.\n- `voice_internal_error`: Listing the voices failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/VoiceInternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "List webhooks",
        "description": "Lists the workspace's webhooks, newest first, with their delivery statistics. The response is a bare array with no paging. It includes the webhooks the CLI listener and integrations create, which the 10-webhook limit on `POST /api/v1/webhooks` does not stop, so it can hold more than 10.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "list"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookList: Every webhook of the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookList"
                },
                "examples": {
                  "default": {
                    "summary": "The account's one webhook, the one this run created.",
                    "value": [
                      {
                        "id": "whk_placeholder1",
                        "url": "https://localhost/sendly-contract-capture",
                        "events": [
                          "message.received"
                        ],
                        "description": "Contract capture",
                        "mode": "test",
                        "is_active": true,
                        "failure_count": 0,
                        "circuit_state": "closed",
                        "api_version": "2024-01",
                        "metadata": {
                          "purpose": "contract-capture"
                        },
                        "created_at": "2026-01-01T00:00:00.000Z",
                        "updated_at": "2026-01-01T00:00:00.000Z",
                        "total_deliveries": 0,
                        "successful_deliveries": 0,
                        "success_rate": 0,
                        "last_delivery_at": null
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Missing Authorization header. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The webhooks could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "summary": "Create a webhook",
        "description": "Creates a webhook and returns its signing secret, the only time it is shown. It is refused once the workspace has 10 webhooks or more, counting those the CLI listener and integrations create.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "create"
        },
        "x-sendly-visibility": "public",
        "requestBody": {
          "description": "The webhook to create.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- WebhookCreated: The webhook was created. Its delivery statistics are always 0 and `null` here.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreated"
                },
                "examples": {
                  "default": {
                    "summary": "A test key's webhook to a test URL, for sandbox events only.",
                    "value": {
                      "id": "whk_placeholder1",
                      "url": "https://localhost/sendly-contract-capture",
                      "events": [
                        "message.received"
                      ],
                      "description": "Contract capture",
                      "mode": "test",
                      "is_active": true,
                      "failure_count": 0,
                      "circuit_state": "closed",
                      "api_version": "2024-01",
                      "metadata": {
                        "purpose": "contract-capture"
                      },
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z",
                      "total_deliveries": 0,
                      "successful_deliveries": 0,
                      "success_rate": 0,
                      "last_delivery_at": null,
                      "secret": "whsec_placeholder"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_url`: `url` does not start with `https://`, as an `http://` URL, a test URL included. Checked before the test key's URL rule.\n- `validation_error`: `url` is missing or names a private or restricted network, or `mode` is not `all`, `test` or `live`.\n- `validation_error`: `url` is not a valid URL, `events` is missing, empty or names an unknown event, or another field has the wrong type.\n- `test_key_restriction`: A test key asked for a URL that is not a test URL.\n- `limit_exceeded`: The workspace already has 10 webhooks or more.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WebhookHttpsRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string"
                              },
                              "message": {
                                "type": "string"
                              },
                              "path": {
                                "type": "array",
                                "items": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "integer"
                                    }
                                  ]
                                }
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "path"
                            ],
                            "description": "A validation issue. More fields describe some kinds of issue."
                          },
                          "description": "What was wrong with `url`, `events` or another field."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "details"
                      ],
                      "title": "validation_error: invalid webhook data",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "test_key_restriction"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "test_key_restriction",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "test_key_restriction"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "limit_exceeded"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "limit_exceeded",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "limit_exceeded"
                      ]
                    }
                  ]
                },
                "examples": {
                  "invalid-webhook-data": {
                    "summary": "A test key's plain-HTTP localhost URL, which fails the HTTPS check.",
                    "value": {
                      "error": "validation_error",
                      "message": "Invalid webhook data",
                      "details": [
                        {
                          "code": "invalid_string",
                          "validation": {
                            "startsWith": "https://"
                          },
                          "message": "HTTPS required for security",
                          "path": [
                            "url"
                          ]
                        }
                      ]
                    }
                  },
                  "default": {
                    "summary": "The URL is missing.",
                    "value": {
                      "error": "validation_error",
                      "message": "URL is required"
                    }
                  },
                  "test-key-restriction": {
                    "summary": "A test key asked for a URL that is not a test URL.",
                    "value": {
                      "error": "test_key_restriction",
                      "message": "Test API keys can only create webhooks to test URLs (localhost, ngrok, webhook.site, etc.)"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "invalid_api_key",
                      "message": "Invalid or expired API key"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `verification_required`: `mode` is `live` and the business is not verified.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "verification_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "verification_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "verification_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The webhook could not be created, or `url` is not a string.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/event-types": {
      "get": {
        "operationId": "listWebhookEventTypes",
        "summary": "List webhook event types",
        "description": "Lists every event a webhook can subscribe to. Needs no API key.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "x-sendly-auth": "public",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "listEventTypeDetails"
        },
        "x-sendly-visibility": "public",
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookEventTypeList: Every event type, with a description.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEventTypeList"
                },
                "examples": {
                  "default": {
                    "summary": "Every event type, without credentials.",
                    "value": {
                      "events": [
                        {
                          "type": "message.sent",
                          "description": "Message has been accepted by the carrier and is being sent"
                        },
                        {
                          "type": "message.delivered",
                          "description": "Message has been successfully delivered to the recipient"
                        },
                        {
                          "type": "message.read",
                          "description": "The recipient read an outbound WhatsApp or RCS message. SMS has no read receipts."
                        },
                        {
                          "type": "message.failed",
                          "description": "Message delivery failed permanently"
                        },
                        {
                          "type": "message.bounced",
                          "description": "Message bounced due to invalid recipient or carrier rejection"
                        },
                        {
                          "type": "message.retrying",
                          "description": "Message delivery failed temporarily and the send is being retried"
                        },
                        {
                          "type": "message.received",
                          "description": "An inbound message was received from a recipient"
                        },
                        {
                          "type": "message.opt_out",
                          "description": "Recipient opted out of messages (texted STOP)"
                        },
                        {
                          "type": "message.opt_in",
                          "description": "Recipient opted back in to messages (texted START/UNSTOP)"
                        },
                        {
                          "type": "verification.created",
                          "description": "A verification was started and its code was sent"
                        },
                        {
                          "type": "verification.delivered",
                          "description": "The verification code was delivered to the phone"
                        },
                        {
                          "type": "verification.verified",
                          "description": "The correct code was entered and the phone is verified"
                        },
                        {
                          "type": "verification.expired",
                          "description": "The verification expired before the correct code was entered"
                        },
                        {
                          "type": "verification.failed",
                          "description": "The verification failed after the maximum number of attempts"
                        },
                        {
                          "type": "verification.resent",
                          "description": "The verification code was sent again"
                        },
                        {
                          "type": "verification.delivery_failed",
                          "description": "The verification code could not be delivered to the phone"
                        },
                        {
                          "type": "conversation.created",
                          "description": "The first message with a phone number was sent or received, starting a conversation"
                        },
                        {
                          "type": "conversation.updated",
                          "description": "A message was sent or received in an existing conversation"
                        },
                        {
                          "type": "draft.created",
                          "description": "A reply draft was created for review. Accepted on subscription but not emitted yet."
                        },
                        {
                          "type": "draft.approved",
                          "description": "A reply draft was approved. Accepted on subscription but not emitted yet."
                        },
                        {
                          "type": "draft.rejected",
                          "description": "A reply draft was rejected. Accepted on subscription but not emitted yet."
                        },
                        {
                          "type": "contact.auto_flagged",
                          "description": "A contact was auto-flagged as unsendable (landline, invalid number, or non-SMS-capable). Fires once per transition from clean to flagged; duplicates on retry or a forced re-check are suppressed."
                        },
                        {
                          "type": "contact.marked_valid",
                          "description": "A contact's auto-flag was cleared via single mark-valid. Future campaigns and batches will include it again. (Bulk operations fire contacts.bulk_marked_valid instead.)"
                        },
                        {
                          "type": "contacts.lookup_completed",
                          "description": "A carrier-lookup sweep finished. Fires once per logical lookup with SWEEP totals (accumulated across all continuations, not just the final run). Includes `sweep_id` for correlation."
                        },
                        {
                          "type": "contacts.bulk_marked_valid",
                          "description": "A bulk mark-valid operation completed. One aggregate event per call (not per contact) with count + up to 1,000 ids; `truncated: true` if more were cleared."
                        },
                        {
                          "type": "brand.verified",
                          "description": "Your 10DLC brand passed carrier identity verification"
                        },
                        {
                          "type": "brand.failed",
                          "description": "Your 10DLC brand failed carrier identity verification"
                        },
                        {
                          "type": "campaign.approved",
                          "description": "Your 10DLC campaign was approved by the carriers and can send"
                        },
                        {
                          "type": "campaign.rejected",
                          "description": "Your 10DLC campaign was rejected or expired. Fetch the campaign for the remediation detail."
                        },
                        {
                          "type": "campaign.suspended",
                          "description": "Your 10DLC campaign was suspended by the carriers. Sending is paused until it is reinstated."
                        },
                        {
                          "type": "assignment.confirmed",
                          "description": "A phone number was registered to your 10DLC campaign and can now send"
                        },
                        {
                          "type": "assignment.failed",
                          "description": "A phone number's registration to your 10DLC campaign failed. It cannot send until resolved."
                        },
                        {
                          "type": "rcs_brand.verified",
                          "description": "The carrier network verified your business for RCS. This happens once per brand, before any agent is reviewed."
                        },
                        {
                          "type": "rcs_brand.failed",
                          "description": "The carrier network could not verify your business for RCS. Carries a `reason`; a corrected registration is needed."
                        },
                        {
                          "type": "rcs_agent.testing",
                          "description": "An RCS agent's branding was approved. It can message the test phones you invited, but nobody else yet."
                        },
                        {
                          "type": "rcs_agent.live",
                          "description": "Carrier launch finished. The RCS agent can message any RCS-capable phone."
                        },
                        {
                          "type": "rcs_agent.rejected",
                          "description": "The carrier network declined an RCS agent. `stage` is `basics` or `launch`, alongside a `reason`."
                        },
                        {
                          "type": "rcs_agent.action_required",
                          "description": "Sendly asked for changes before sending your RCS registration to the carrier network. Carries a `note`."
                        },
                        {
                          "type": "port.completed",
                          "description": "A number you were porting in has landed and can send and receive"
                        },
                        {
                          "type": "port_out.requested",
                          "description": "Another carrier requested to port one of your numbers away. Verify it is authorized."
                        },
                        {
                          "type": "port_out.completed",
                          "description": "A port-out finished. The number has left your account and can no longer send or receive here."
                        },
                        {
                          "type": "port_out.rejected",
                          "description": "A pending port-out was rejected. The number stays with you."
                        },
                        {
                          "type": "port_out.cancelled",
                          "description": "A pending port-out was cancelled by the gaining carrier. The number stays with you."
                        },
                        {
                          "type": "number.activated",
                          "description": "A purchased number finished provisioning and is live"
                        },
                        {
                          "type": "number.failed",
                          "description": "A number order could not activate (carrier rejection or expired requirements). Any hold was released."
                        },
                        {
                          "type": "number.requirements_required",
                          "description": "The carrier needs regulatory details or documents before the number can activate. Includes `requirements_deadline_at`."
                        },
                        {
                          "type": "number.released",
                          "description": "A number was released from your account and can no longer send or receive"
                        },
                        {
                          "type": "whatsapp_account.connected",
                          "description": "A number finished connecting to WhatsApp and can send"
                        },
                        {
                          "type": "whatsapp_account.failed",
                          "description": "A WhatsApp signup or number connection failed. Includes `failureReasons`."
                        },
                        {
                          "type": "whatsapp_template.approved",
                          "description": "Meta approved a WhatsApp template, so it can be sent"
                        },
                        {
                          "type": "whatsapp_template.rejected",
                          "description": "Meta rejected a WhatsApp template. `rejectionReason` says why."
                        },
                        {
                          "type": "whatsapp_template.paused",
                          "description": "Meta paused or disabled a WhatsApp template. `status` says which."
                        },
                        {
                          "type": "call.started",
                          "description": "A call was answered"
                        },
                        {
                          "type": "call.completed",
                          "description": "A call ended, for any reason. `status` is completed, cancelled, declined, no_answer, busy or failed."
                        },
                        {
                          "type": "call.recording.ready",
                          "description": "A call recording finished processing and can be fetched from the API"
                        },
                        {
                          "type": "short_code.action_required",
                          "description": "Your short code application needs you. `stage` is `changes` (with a `note`) or `signatures`."
                        },
                        {
                          "type": "short_code.rejected",
                          "description": "Your short code application could not go forward. Carries a `reason`."
                        },
                        {
                          "type": "short_code.filed",
                          "description": "Every form is signed and the short code application is with the carriers"
                        },
                        {
                          "type": "short_code.live",
                          "description": "The short code is approved everywhere and ready to send. Carries `short_code`."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyError"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: the capture client cannot send a GET with a body, and through sendly.live the edge answers one with its own 500 (error 1101) before the server sees it. The server's JSON body parser sends this for a body that cannot be parsed, as sendMessage.400.invalid-json shows.",
                    "value": {
                      "message": "Unexpected end of JSON input"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnhandledServerError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}": {
      "get": {
        "operationId": "getWebhook",
        "summary": "Get a webhook",
        "description": "Returns one webhook. Its delivery statistics are always 0 and `null` here: read them from `GET /api/v1/webhooks`.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "get"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Webhook: The webhook.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                },
                "examples": {
                  "default": {
                    "summary": "The webhook this run created.",
                    "value": {
                      "id": "whk_placeholder1",
                      "url": "https://localhost/sendly-contract-capture",
                      "events": [
                        "message.received"
                      ],
                      "description": "Contract capture",
                      "mode": "test",
                      "is_active": true,
                      "failure_count": 0,
                      "circuit_state": "closed",
                      "api_version": "2024-01",
                      "metadata": {
                        "purpose": "contract-capture"
                      },
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z",
                      "total_deliveries": 0,
                      "successful_deliveries": 0,
                      "success_rate": 0,
                      "last_delivery_at": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no webhook.",
                    "value": {
                      "error": "not_found",
                      "message": "Webhook not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The webhook could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateWebhook",
        "summary": "Update a webhook",
        "description": "Changes a webhook's URL, events, description, mode, metadata or whether it is active. Its delivery statistics are always 0 and `null` in the answer.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "update"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- Webhook: The updated webhook.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                },
                "examples": {
                  "default": {
                    "summary": "A new description.",
                    "value": {
                      "id": "whk_placeholder1",
                      "url": "https://localhost/sendly-contract-capture",
                      "events": [
                        "message.received"
                      ],
                      "description": "Contract capture, updated",
                      "mode": "test",
                      "is_active": true,
                      "failure_count": 0,
                      "circuit_state": "closed",
                      "api_version": "2024-01",
                      "metadata": {
                        "purpose": "contract-capture"
                      },
                      "created_at": "2026-01-01T00:00:00.000Z",
                      "updated_at": "2026-01-01T00:00:00.000Z",
                      "total_deliveries": 0,
                      "successful_deliveries": 0,
                      "success_rate": 0,
                      "last_delivery_at": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_url`: `url` changes to one that does not start with `https://`.\n- `validation_error`: `is_active` is not a boolean, no field to change was sent, `mode` is not `all`, `test` or `live`, or `events` is not an array or names an unknown event.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WebhookHttpsRequiredError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "validation_error"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "validation_error",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "validation_error"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "`is_active` is not a boolean.",
                    "value": {
                      "error": "validation_error",
                      "message": "is_active must be a boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.\n- `verification_required`: `mode` is `live` and the business is not verified.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "verification_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "verification_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "verification_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no webhook.",
                    "value": {
                      "error": "not_found",
                      "message": "Webhook not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The webhook could not be updated, as when `url` is not a string, a field has a type the database refuses, or a key with no workspace changes a webhook its user created in a workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Delete a webhook",
        "description": "Deletes a webhook and its delivery history.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "delete"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.\n\n- The webhook was deleted. A key with no workspace gets this too for a webhook its user created in a workspace, which is not deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "The same webhook again, now deleted.",
                    "value": {
                      "error": "not_found",
                      "message": "Webhook not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The webhook could not be deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/backfill": {
      "post": {
        "operationId": "backfillWebhookDeliveries",
        "summary": "Backfill missed message events",
        "description": "Rebuilds the `message.sent`, `message.delivered` and `message.failed` events of the live messages the webhook's creator sent in a window (in the webhook's workspace, for a workspace webhook) that have no delivered or pending delivery on this webhook, and sends them, whatever the webhook's `mode`. A rebuilt event has the event id the original would have had, and one that already has a failed delivery is left to `redeliver`. `since` and `until` are ISO 8601 timestamps that default to the last 24 hours. `since` must be earlier than `until`, and the window can be at most 7 days (`Backfill window cannot exceed 7 days`).",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "backfill"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The window and events.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BackfillWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookBackfillResult: The missed events were rebuilt and sent. None missing is a 200 too.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookBackfillResult"
                },
                "examples": {
                  "default": {
                    "summary": "The last 24 hours, for a webhook subscribed to no message event a backfill rebuilds.",
                    "value": {
                      "message": "No missed events found in the given window",
                      "run_id": "recover_placeholder5",
                      "synthesized": 0,
                      "by_type": {},
                      "truncated": false,
                      "candidates_scanned": 0,
                      "delivery_ids": [],
                      "since": "2026-01-01T00:00:00.000Z",
                      "until": "2026-01-01T00:00:00.000Z",
                      "limit": 1000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `since` or `until` is not a timestamp, or the window is empty or longer than 7 days.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A window longer than 7 days.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Backfill window cannot exceed 7 days"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no webhook.",
                    "value": {
                      "error": "not_found",
                      "message": "Webhook not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `circuit_open`: The webhook's circuit breaker is open.\n- `webhook_inactive`: The webhook is disabled.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "circuit_open"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "circuit_state": {
                          "type": "string",
                          "enum": [
                            "open"
                          ]
                        },
                        "circuit_opened_at": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "When the circuit opened. ISO 8601, in UTC."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "circuit_state",
                        "circuit_opened_at"
                      ],
                      "title": "circuit_open, with when it opened",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "circuit_open"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "webhook_inactive"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "webhook_inactive",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "webhook_inactive"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The webhook is disabled.",
                    "value": {
                      "error": "webhook_inactive",
                      "message": "Webhook is disabled. Re-enable it before backfilling."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The events could not be backfilled.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "summary": "List a webhook's deliveries",
        "description": "Lists a webhook's deliveries, newest first.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "limit-offset",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "getDeliveries"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Page size, 1 to 100. Defaults to 50, which is also what 0 or a value that is not a number gives. A value below 1 is raised to 1, and one above 100 is lowered to 100."
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many deliveries to skip. Ignored when `page` is set."
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "The page to return, starting at 1. Takes precedence over `offset`, and sets the `offset` in the answer."
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "delivered",
                "failed",
                "cancelled"
              ],
              "description": "Only deliveries with this status."
            },
            "required": false,
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookDeliveryList: A page of deliveries.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryList"
                },
                "examples": {
                  "default": {
                    "summary": "The webhook's deliveries: the failed test event.",
                    "value": {
                      "deliveries": [
                        {
                          "id": "del_placeholder2",
                          "webhook_id": "whk_placeholder1",
                          "event_id": "00000000-0000-4000-8000-000000000001",
                          "event_type": "webhook.test",
                          "status": "failed",
                          "success": false,
                          "response_status_code": null,
                          "http_status": 0,
                          "response_time": null,
                          "response_time_ms": 0,
                          "response_body": null,
                          "error_message": "URL blocked by SSRF protection",
                          "error_code": "ssrf_blocked",
                          "attempt_number": 1,
                          "max_attempts": 1,
                          "next_retry_at": null,
                          "created_at": "2026-01-01T00:00:00.000Z",
                          "delivered_at": null
                        }
                      ],
                      "pagination": {
                        "limit": 5,
                        "offset": 0
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no webhook.",
                    "value": {
                      "error": "not_found",
                      "message": "Webhook not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The deliveries could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/deliveries/{deliveryId}": {
      "get": {
        "operationId": "getWebhookDelivery",
        "summary": "Get a webhook delivery",
        "description": "Returns one delivery of a webhook, in the list's format.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The delivery's id, such as `del_...`."
            },
            "required": true,
            "name": "deliveryId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookDeliveryResult: The delivery.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResult"
                },
                "examples": {
                  "default": {
                    "summary": "The failed test event's delivery.",
                    "value": {
                      "delivery": {
                        "id": "del_placeholder2",
                        "webhook_id": "whk_placeholder1",
                        "event_id": "00000000-0000-4000-8000-000000000001",
                        "event_type": "webhook.test",
                        "status": "failed",
                        "success": false,
                        "response_status_code": null,
                        "http_status": 0,
                        "response_time": null,
                        "response_time_ms": 0,
                        "response_body": null,
                        "error_message": "URL blocked by SSRF protection",
                        "error_code": "ssrf_blocked",
                        "attempt_number": 1,
                        "max_attempts": 1,
                        "next_retry_at": null,
                        "created_at": "2026-01-01T00:00:00.000Z",
                        "delivered_at": null
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace) (`Webhook not found`), or the webhook has no delivery with this id (`Delivery not found`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "A delivery id the webhook does not have.",
                    "value": {
                      "error": "not_found",
                      "message": "Delivery not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The delivery could not be read.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/deliveries/{deliveryId}/retry": {
      "post": {
        "operationId": "retryWebhookDelivery",
        "summary": "Retry a webhook delivery",
        "description": "Sends one delivery's event again, with its original event id.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "retryDelivery"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The delivery's id, such as `del_...`."
            },
            "required": true,
            "name": "deliveryId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookDeliveryRetry: The event was sent again, or queued to be.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryRetry"
                },
                "examples": {
                  "default": {
                    "summary": "The failed test event, sent again.",
                    "value": {
                      "delivery": {
                        "id": "del_placeholder6",
                        "webhook_id": "whk_placeholder1",
                        "event_id": "00000000-0000-4000-8000-000000000001",
                        "event_type": "webhook.test",
                        "status": "pending",
                        "success": false,
                        "response_status_code": null,
                        "http_status": 0,
                        "response_time": null,
                        "response_time_ms": 0,
                        "response_body": null,
                        "error_message": null,
                        "error_code": null,
                        "attempt_number": 1,
                        "max_attempts": 6,
                        "next_retry_at": null,
                        "created_at": "2026-01-01T00:00:00.000Z",
                        "delivered_at": null
                      },
                      "requeued": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace) (`Webhook not found`), or the webhook has no delivery with this id (`Delivery not found`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "A delivery id the webhook does not have.",
                    "value": {
                      "error": "not_found",
                      "message": "Delivery not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `webhook_inactive`: The webhook is disabled.\n- `circuit_open`: The webhook's circuit breaker is open.\n- `delivery_in_progress`: The delivery is already queued.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "webhook_inactive"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "webhook_inactive",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "webhook_inactive"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "circuit_open"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "circuit_state": {
                          "type": "string",
                          "enum": [
                            "open"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "circuit_state"
                      ],
                      "title": "circuit_open",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "circuit_open"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "delivery_in_progress"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "delivery_in_progress",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "delivery_in_progress"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The webhook is disabled.",
                    "value": {
                      "error": "webhook_inactive",
                      "message": "Webhook is disabled. Re-enable it before retrying a delivery."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The delivery could not be retried.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/recovery-preview": {
      "get": {
        "operationId": "getWebhookRecoveryPreview",
        "summary": "Preview a recovery",
        "description": "Counts what `redeliver` and `backfill` would send for a window, without sending anything. `since` and `until` are ISO 8601 timestamps that default to the last 24 hours. `since` must be earlier than `until`, and the window can be at most 7 days (`Preview window cannot exceed 7 days`).",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "The window's start. Defaults to 24 hours ago."
            },
            "required": false,
            "name": "since",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "The window's end. Defaults to now."
            },
            "required": false,
            "name": "until",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated event types to count. Defaults to all."
            },
            "required": false,
            "name": "event_types",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookRecoveryPreview: The preview.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookRecoveryPreview"
                },
                "examples": {
                  "default": {
                    "summary": "The last 24 hours: the failed test event.",
                    "value": {
                      "circuitState": "closed",
                      "circuitOpenedAt": null,
                      "failureCount": 0,
                      "auditFailures": {
                        "total": 1,
                        "byStatus": {
                          "failed": 1
                        },
                        "byEventType": {
                          "webhook.test": 1
                        }
                      },
                      "missingFromMessages": {
                        "total": 0,
                        "byEventType": {}
                      },
                      "histogram": [
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 0
                        },
                        {
                          "bucket": "2026-01-01T00:00:00.000Z",
                          "missing": 0,
                          "failed": 1
                        }
                      ],
                      "samples": [
                        {
                          "id": "test_msg_00000000-0000-4000-8000-000000000002",
                          "toMasked": "+1*****7890",
                          "eventType": "webhook.test",
                          "occurredAt": "2026-01-01T00:00:00.000Z"
                        }
                      ],
                      "windowSuggestion": null,
                      "since": "2026-01-01T00:00:00.000Z",
                      "until": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `since` or `until` is not a timestamp, or the window is empty or longer than 7 days.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "`since` is not a timestamp.",
                    "value": {
                      "error": "invalid_request",
                      "message": "since and until must be valid ISO timestamps"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:read), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no webhook.",
                    "value": {
                      "error": "not_found",
                      "message": "Webhook not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The preview could not be computed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/redeliver": {
      "post": {
        "operationId": "redeliverWebhookDeliveries",
        "summary": "Redeliver a window of deliveries",
        "description": "Sends again the webhook's recorded deliveries created in a window, oldest first, each with its original event id. `since` and `until` are ISO 8601 timestamps that default to the last 24 hours. `since` must be earlier than `until`, and the window can be at most 7 days (`Replay window cannot exceed 7 days`).",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "redeliver"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The window and filters. Every field is optional.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RedeliverWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookRedeliverResult: The matching deliveries were requeued. None matching is a 200 too.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookRedeliverResult"
                },
                "examples": {
                  "default": {
                    "summary": "The last 24 hours' failed and cancelled deliveries: the test event.",
                    "value": {
                      "message": "Requeued 1 webhook delivery",
                      "run_id": "recover_placeholder3",
                      "requeued": 1,
                      "skipped": 0,
                      "truncated": false,
                      "window_size": 1,
                      "delivery_ids": [
                        "del_placeholder4"
                      ],
                      "since": "2026-01-01T00:00:00.000Z",
                      "until": "2026-01-01T00:00:00.000Z",
                      "limit": 10
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `since` or `until` is not a timestamp, the window is empty or longer than 7 days, or `statuses` has a status that is not `failed`, `cancelled`, `delivered` or `pending`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "`since` is later than `until`.",
                    "value": {
                      "error": "invalid_request",
                      "message": "since must be earlier than until"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no webhook.",
                    "value": {
                      "error": "not_found",
                      "message": "Webhook not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `circuit_open`: The webhook's circuit breaker is open.\n- `webhook_inactive`: The webhook is disabled.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "circuit_open"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "circuit_state": {
                          "type": "string",
                          "enum": [
                            "open"
                          ]
                        },
                        "circuit_opened_at": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "When the circuit opened. ISO 8601, in UTC."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "circuit_state",
                        "circuit_opened_at"
                      ],
                      "title": "circuit_open, with when it opened",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "circuit_open"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "webhook_inactive"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "webhook_inactive",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "webhook_inactive"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The webhook is disabled.",
                    "value": {
                      "error": "webhook_inactive",
                      "message": "Webhook is disabled. Re-enable it before replaying."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The deliveries could not be redelivered.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/reset-circuit": {
      "post": {
        "operationId": "resetWebhookCircuit",
        "summary": "Reset a webhook's circuit breaker",
        "description": "Closes an open or half-open circuit breaker and clears the failure count, so deliveries go again without waiting for the cool-down. A circuit that is already closed is left as it is, failure count included.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "resetCircuit"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookCircuitReset: The circuit is closed: it already was (`Circuit is already closed`, nothing changed), or it was open or half open and is now reset. The webhook's delivery statistics are always 0 and `null` here.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCircuitReset"
                },
                "examples": {
                  "default": {
                    "summary": "A circuit that is already closed.",
                    "value": {
                      "message": "Circuit is already closed",
                      "webhook": {
                        "id": "whk_placeholder1",
                        "url": "https://localhost/sendly-contract-capture",
                        "events": [
                          "message.received"
                        ],
                        "description": "Contract capture, updated",
                        "mode": "test",
                        "is_active": true,
                        "failure_count": 0,
                        "circuit_state": "closed",
                        "api_version": "2024-01",
                        "metadata": {
                          "purpose": "contract-capture"
                        },
                        "created_at": "2026-01-01T00:00:00.000Z",
                        "updated_at": "2026-01-01T00:00:00.000Z",
                        "total_deliveries": 0,
                        "successful_deliveries": 0,
                        "success_rate": 0,
                        "last_delivery_at": null
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no webhook.",
                    "value": {
                      "error": "not_found",
                      "message": "Webhook not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The circuit could not be reset.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/rotate-secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "summary": "Rotate a webhook's secret",
        "description": "Replaces the webhook's signing secret and returns the new one, the only time it is shown. Deliveries are signed with it at once, and the old secret stops working.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "rotateSecret"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookSecretRotation: The secret was rotated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSecretRotation"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code: since main's #195 (a3f1820f) rotateWebhookSecretV1 raises the secret version, answers `grace_period_hours: 0` and says the previous secret stopped working. The production capture of 2026-10-03 predates that change. It was: A new secret for the webhook this run created.",
                    "value": {
                      "success": true,
                      "id": "whk_placeholder1",
                      "secret": "whsec_placeholder",
                      "new_secret": "whsec_placeholder",
                      "new_secret_version": 2,
                      "grace_period_hours": 0,
                      "rotated_at": "2026-01-01T00:00:00.000Z",
                      "message": "Webhook secret rotated successfully. The previous secret stopped working immediately. Save this secret - it won't be shown again."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: No webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no webhook.",
                    "value": {
                      "error": "not_found",
                      "message": "Webhook not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.\n- `internal_error`: The secret could not be rotated, as when a key with no workspace rotates a webhook its user created in a workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/test": {
      "post": {
        "operationId": "testWebhook",
        "summary": "Send a test event",
        "description": "Posts a `webhook.test` event to the webhook's URL and waits for the answer, up to 30 seconds. The attempt is recorded as a delivery with one attempt, and a timeout, connection error or 5xx answer counts toward the circuit breaker.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "apiKey",
        "x-sendly-scopes": [
          "webhooks:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "webhooks",
          "method": "test"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The webhook's id, such as `whk_...`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WebhookTestResult: Your endpoint answered with a 2xx status.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTestResult"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the code, not captured: a test key can only point a webhook at a test URL, and delivery refuses localhost, so no endpoint the capture may use answers 2xx. The test event was accepted with a 200.",
                    "value": {
                      "success": true,
                      "message": "Test webhook delivered successfully in 182ms",
                      "delivery": {
                        "id": "del_placeholder2",
                        "delivery_id": "del_placeholder2",
                        "webhook_url": "https://example.com/webhooks/sendly",
                        "event_type": "webhook.test",
                        "status": "delivered",
                        "response_time": 182,
                        "status_code": 200,
                        "response_body": "{\"received\":true}",
                        "delivered_at": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- Test webhook failed: The test failed: no webhook with this id belongs to the key's workspace (for a key with no workspace: was created by the key's user, in any workspace), the webhook is disabled or its circuit is open, the URL is blocked, your endpoint did not answer 2xx in time, or recording the delivery failed (`message` then carries the internal error text).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "success": {
                          "type": "boolean",
                          "enum": [
                            false
                          ]
                        },
                        "message": {
                          "type": "string",
                          "description": "`Test webhook failed: ` and the reason, or `Webhook not found or access denied`."
                        },
                        "sendlyCode": {
                          "type": "string",
                          "enum": [
                            "webhook_test_failed"
                          ],
                          "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
                        }
                      },
                      "required": [
                        "success",
                        "message"
                      ],
                      "description": "Has no `error` field: `success` is `false` and `message` says why.",
                      "title": "Test webhook failed",
                      "x-sendly-error-shape": "codeless",
                      "x-sendly-error-codes": [],
                      "x-sendly-proposed-codes": [
                        "webhook_test_failed"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The test event to a localhost URL, which delivery refuses.",
                    "value": {
                      "success": false,
                      "message": "Test webhook failed: URL blocked by SSRF protection"
                    }
                  },
                  "not-found": {
                    "summary": "An id that matches no webhook, which this endpoint answers with a 400.",
                    "value": {
                      "success": false,
                      "message": "Webhook not found or access denied"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`, `invalid_auth_format`, `invalid_key_format`, `invalid_api_key`, `invalid_cli_token`, `invalid_token`: The Authorization header is missing or malformed, or the key or CLI session is unknown, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: The key lacks a required scope (webhooks:write), a team workspace's key was made by someone who is no longer an active member (removed, or suspended) and does not own the workspace, or a CLI session is not an active member of the workspace it asked for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: The key has used its requests for this minute: 60 for a test key or a CLI session, 600 for a live key, 3,000 for an enterprise master key.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The key could not be checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/senders": {
      "get": {
        "operationId": "listWhatsAppSenders",
        "summary": "List WhatsApp senders",
        "description": "Lists the workspace's numbers that are connected, or connecting, to WhatsApp, newest first. Failed and released connections are left out.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.senders",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSenderList: The senders.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSenderList"
                },
                "examples": {
                  "default": {
                    "summary": "The mock workspace, whose WhatsApp connections all failed or were released.",
                    "value": {
                      "senders": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:read). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `server_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/senders/{phoneNumber}": {
      "delete": {
        "operationId": "disconnectWhatsAppSender",
        "summary": "Disconnect a WhatsApp sender",
        "description": "Takes a connected number off WhatsApp. It stops sending and receiving WhatsApp messages; SMS and calls on the number keep working. When it was the business account's last connected number, the account is marked disconnected. Connect the number again with `POST /api/v1/whatsapp/signup`. Disconnecting a number that is already disconnected answers 200.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The sender's number. Every character but the digits is dropped and a `+` is added, so `15555550100` and `+1 (555) 555-0100` name the same sender."
            },
            "required": true,
            "name": "phoneNumber",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSenderDisconnected: The number is disconnected from WhatsApp, now or already.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSenderDisconnected"
                },
                "examples": {
                  "default": {
                    "summary": "A connected number is disconnected from WhatsApp. Built from disconnectWhatsappSender, not captured: the route is new.",
                    "value": {
                      "phoneNumber": "+15555550100",
                      "disconnected": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `whatsapp_sender_not_connected`: The number was never connected to WhatsApp in this workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSenderNotConnectedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "The number was never connected to WhatsApp in the workspace. Built from disconnectWhatsappSender, not captured: the route is new.",
                    "value": {
                      "error": "whatsapp_sender_not_connected",
                      "message": "This number isn't connected to WhatsApp in this workspace."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `whatsapp_signup_in_progress`: The number's connection has not finished. Cancel the signup instead.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "whatsapp_signup_in_progress"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "id": {
                      "type": "string",
                      "description": "The signup in progress, to pass to `POST /api/v1/whatsapp/signup/{id}/cancel`."
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "The number is still connecting",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "whatsapp_signup_in_progress"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/senders/{phoneNumber}/calling": {
      "patch": {
        "operationId": "updateWhatsAppSenderCalling",
        "summary": "Turn WhatsApp calling on or off",
        "description": "Switches WhatsApp calling on or off for an active sender. Turning it on needs calls turned on for the number first, so WhatsApp calls have somewhere to ring.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.senders",
          "method": "setCalling"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The sender's number. Every character but the digits is dropped and a `+` is added, so `15555550100` and `+1 (555) 555-0100` name the same sender."
            },
            "required": true,
            "name": "phoneNumber",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "Whether calling should be on.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWhatsAppCallingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppCallingSettings: The calling setting WhatsApp now has.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppCallingSettings"
                },
                "examples": {
                  "default": {
                    "summary": "Calling turned on for a US number, which WhatsApp never lets the business call out from. Built from setWaSenderCalling, not captured: it needs a live key and changes the sender on WhatsApp.",
                    "value": {
                      "phoneNumber": "+15555550100",
                      "callingEnabled": true,
                      "outboundCallingAllowed": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `enabled` is not `true` or `false`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to turn WhatsApp calling on, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot change WhatsApp calling."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `whatsapp_sender_not_connected`: The number is not an active WhatsApp sender of this workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSenderNotConnectedError"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `voice_not_enabled`: Turning calling on for a number whose calls are not turned on in its voice settings.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceNotEnabledError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.\n- `whatsapp_calling_unavailable`: WhatsApp refused, or answered with calling still off: it allows calling only once the account may message at least 2,000 people a day and the display name is approved.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/DisposableEmailError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_calling_unavailable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_calling_unavailable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_calling_unavailable"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_calling_update_failed`: WhatsApp could not be reached, or failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "whatsapp_calling_update_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "whatsapp_calling_update_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "whatsapp_calling_update_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/senders/{phoneNumber}/conversational_components": {
      "get": {
        "operationId": "getWhatsAppConversationalComponents",
        "summary": "Get a sender's conversation starters",
        "description": "Reads an active sender's ice breakers and commands from WhatsApp.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.senders",
          "method": "getConversationalComponents"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The sender's number. Every character but the digits is dropped and a `+` is added, so `15555550100` and `+1 (555) 555-0100` name the same sender."
            },
            "required": true,
            "name": "phoneNumber",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppConversationalComponents: The sender's ice breakers and commands.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppConversationalComponents"
                },
                "examples": {
                  "default": {
                    "summary": "An active sender's ice breakers and commands. Built from getWaConversationalComponents, not captured: the mock workspace has no active WhatsApp sender.",
                    "value": {
                      "phoneNumber": "+15555550100",
                      "iceBreakers": [
                        "What are your hours?"
                      ],
                      "commands": [
                        {
                          "command": "hours",
                          "description": "Our opening hours"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:read). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `whatsapp_sender_not_connected`: The number is not an active WhatsApp sender of this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSenderNotConnectedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A number that is not a WhatsApp sender of the workspace.",
                    "value": {
                      "error": "whatsapp_sender_not_connected",
                      "message": "This number isn't connected to WhatsApp yet."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_conversational_components_fetch_failed`: WhatsApp did not return them.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "whatsapp_conversational_components_fetch_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "whatsapp_conversational_components_fetch_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "whatsapp_conversational_components_fetch_failed"
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateWhatsAppConversationalComponents",
        "summary": "Update a sender's conversation starters",
        "description": "Replaces an active sender's ice breakers, commands, or both, on WhatsApp.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.senders",
          "method": "updateConversationalComponents"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The sender's number. Every character but the digits is dropped and a `+` is added, so `15555550100` and `+1 (555) 555-0100` name the same sender."
            },
            "required": true,
            "name": "phoneNumber",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The lists to replace.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWhatsAppConversationalComponentsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppConversationalComponents: The ice breakers and commands WhatsApp now has.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppConversationalComponents"
                },
                "examples": {
                  "default": {
                    "summary": "The lists after both were replaced. Built from updateWaConversationalComponents, not captured: it needs a live key and changes the sender on WhatsApp.",
                    "value": {
                      "phoneNumber": "+15555550100",
                      "iceBreakers": [
                        "What are your hours?"
                      ],
                      "commands": [
                        {
                          "command": "hours",
                          "description": "Our opening hours"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: The body breaks one of the rules on the lists.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to change a sender's conversation starters, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot update sender settings."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `whatsapp_sender_not_connected`: The number is not an active WhatsApp sender of this workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSenderNotConnectedError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_conversational_components_update_failed`: WhatsApp did not take the change.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "whatsapp_conversational_components_update_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "whatsapp_conversational_components_update_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "whatsapp_conversational_components_update_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/senders/{phoneNumber}/profile": {
      "get": {
        "operationId": "getWhatsAppSenderProfile",
        "summary": "Get a sender's business profile",
        "description": "Reads an active sender's business profile from WhatsApp.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.senders",
          "method": "getProfile"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The sender's number. Every character but the digits is dropped and a `+` is added, so `15555550100` and `+1 (555) 555-0100` name the same sender."
            },
            "required": true,
            "name": "phoneNumber",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSenderProfile: The profile.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSenderProfile"
                },
                "examples": {
                  "default": {
                    "summary": "An active sender's business profile. Built from the handler and its projection, not captured: the mock workspace has no active WhatsApp sender, and connecting one costs the $9.99 connection fee.",
                    "value": {
                      "phoneNumber": "+15555550100",
                      "displayName": "Acme Bakery",
                      "profilePhotoUrl": "https://example.com/acme-bakery.jpg",
                      "category": null,
                      "about": "Fresh bread every morning",
                      "description": null,
                      "email": "user@example.com",
                      "website": "https://example.com",
                      "address": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:read). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `whatsapp_sender_not_connected`: The number is not an active WhatsApp sender of this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSenderNotConnectedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A number that is not a WhatsApp sender of the workspace.",
                    "value": {
                      "error": "whatsapp_sender_not_connected",
                      "message": "This number isn't connected to WhatsApp yet."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `server_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_profile_fetch_failed`: WhatsApp did not return the profile.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "whatsapp_profile_fetch_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "whatsapp_profile_fetch_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "whatsapp_profile_fetch_failed"
                  ]
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateWhatsAppSenderProfile",
        "summary": "Update a sender's business profile",
        "description": "Writes the given fields to an active sender's business profile on WhatsApp.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.senders",
          "method": "updateProfile"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The sender's number. Every character but the digits is dropped and a `+` is added, so `15555550100` and `+1 (555) 555-0100` name the same sender."
            },
            "required": true,
            "name": "phoneNumber",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWhatsAppSenderProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSenderProfile: The profile as WhatsApp returned it after the change.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSenderProfile"
                },
                "examples": {
                  "default": {
                    "summary": "The profile after a change to `about`. Built from the handler and its projection, not captured: it needs a live key and changes the sender's profile on WhatsApp.",
                    "value": {
                      "phoneNumber": "+15555550100",
                      "displayName": "Acme Bakery",
                      "profilePhotoUrl": "https://example.com/acme-bakery.jpg",
                      "category": null,
                      "about": "Open every day",
                      "description": null,
                      "email": "user@example.com",
                      "website": "https://example.com",
                      "address": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: The body is not an object, names a field that is not a profile field, has a field that is not a string or is too long, or has no fields.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to change a sender's profile, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot update sender profiles."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `whatsapp_sender_not_connected`: The number is not an active WhatsApp sender of this workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSenderNotConnectedError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_profile_update_failed`: WhatsApp did not take the change.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppProfileUpdateFailedError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/senders/{phoneNumber}/profile/photo": {
      "post": {
        "operationId": "uploadWhatsAppSenderProfilePhoto",
        "summary": "Upload a sender's profile photo",
        "description": "Sets an active sender's profile photo. Send `multipart/form-data` with one file in the field `file`: a JPEG or PNG of at most 5 MB, checked by its bytes. WhatsApp wants it square and at least 192 pixels wide.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.senders",
          "method": "uploadProfilePhoto"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The sender's number. Every character but the digits is dropped and a `+` is added, so `15555550100` and `+1 (555) 555-0100` name the same sender."
            },
            "required": true,
            "name": "phoneNumber",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSenderProfile: The profile after the upload. When WhatsApp's profile cannot be read back, every field but `phoneNumber` and `profilePhotoUrl` is `null`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSenderProfile"
                },
                "examples": {
                  "default": {
                    "summary": "The profile after a JPEG was uploaded as the multipart field `file`. Built from uploadWaProfilePhoto, not captured: it needs a live key and changes the sender's photo on WhatsApp.",
                    "value": {
                      "phoneNumber": "+15555550100",
                      "displayName": "Acme Bakery",
                      "profilePhotoUrl": "https://example.com/acme-bakery-new.jpg",
                      "category": null,
                      "about": "Fresh bread every morning",
                      "description": null,
                      "email": "user@example.com",
                      "website": "https://example.com",
                      "address": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: The multipart body cannot be read, has more than one file, or has a file in a field other than `file`.\n- `file_required`: No file came in the `file` field.\n- `whatsapp_profile_photo_invalid`: The file is not a JPEG or PNG image.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "file_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "file_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "file_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_profile_photo_invalid"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_profile_photo_invalid",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_profile_photo_invalid"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to upload a profile photo, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot update sender profiles."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `whatsapp_sender_not_connected`: The number is not an active WhatsApp sender of this workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSenderNotConnectedError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.\n- `whatsapp_profile_photo_too_large`: The uploaded file is larger than 5 MB.\n- `whatsapp_profile_photo_too_large`: The file is larger than 5 MB.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyTooLargeError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppProfilePhotoTooLargeError"
                    }
                  ]
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `server_error`: The account's WhatsApp access could not be checked.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_profile_update_failed`: WhatsApp did not take the photo.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppProfileUpdateFailedError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWhatsAppSenderProfilePhoto",
        "summary": "Remove a sender's profile photo",
        "description": "Removes an active sender's profile photo. A photo WhatsApp no longer has counts as removed.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.senders",
          "method": "deleteProfilePhoto"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The sender's number. Every character but the digits is dropped and a `+` is added, so `15555550100` and `+1 (555) 555-0100` name the same sender."
            },
            "required": true,
            "name": "phoneNumber",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSenderProfile: The profile after the removal. When WhatsApp's profile cannot be read back, every field but `phoneNumber` is `null`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSenderProfile"
                },
                "examples": {
                  "default": {
                    "summary": "The profile after its photo was removed. Built from removeWaProfilePhoto, not captured: it needs a live key and changes the sender's photo on WhatsApp.",
                    "value": {
                      "phoneNumber": "+15555550100",
                      "displayName": "Acme Bakery",
                      "profilePhotoUrl": null,
                      "category": null,
                      "about": "Fresh bread every morning",
                      "description": null,
                      "email": "user@example.com",
                      "website": "https://example.com",
                      "address": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to remove a profile photo, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot update sender profiles."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `whatsapp_sender_not_connected`: The number is not an active WhatsApp sender of this workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSenderNotConnectedError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_profile_update_failed`: WhatsApp did not remove the photo.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppProfileUpdateFailedError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/signup": {
      "post": {
        "operationId": "startWhatsAppSignup",
        "summary": "Connect a number to WhatsApp",
        "description": "Starts connecting an active workspace number to WhatsApp, for a one-time $9.99 connection fee per number charged to the card on file when the connection starts (refunded automatically if the connection fails, not refundable once the number is connected). Without `businessAccountId`, the answer has a `connectUrl` a person opens to sign in with Facebook; poll `GET /api/v1/whatsapp/signup/{id}` until it is `active`. With the id of a WhatsApp Business account the workspace already connected, WhatsApp sends the number a code instead, to send to `POST /api/v1/whatsapp/signup/{id}/verify`. A signup already in progress for the number is answered with 200 and not charged again.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.signup",
          "method": "create"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The number to connect.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartWhatsAppSignupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSignupSession: A Facebook signup for this number is already in progress.\n- WhatsAppSignup: A number added by code is already waiting for its code, or the code was already asked for.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WhatsAppSignupSession"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSignup"
                    }
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.\n\n- WhatsAppSignupSession: The signup started and the fee was charged.\n- WhatsAppSignup: The number is being added by code: the fee was charged and WhatsApp was asked to send the code.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WhatsAppSignupSession"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSignup"
                    }
                  ]
                },
                "examples": {
                  "add-by-code": {
                    "summary": "A number being added by code to a connected business account. Built from startWhatsappNumberAddition and sendWhatsappNumberVerification, not captured: it needs a live key, charges the $9.99 connection fee and has WhatsApp text the number.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "status": "verifying",
                      "phoneNumber": "+15555550100",
                      "businessAccountId": "100000000000001",
                      "failureReasons": null,
                      "verificationMethod": "sms",
                      "verificationAttemptsRemaining": 5,
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  },
                  "default": {
                    "summary": "A Facebook signup started. Built from startWhatsappSignup, not captured: it needs a live key and charges the $9.99 connection fee.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "connectUrl": "https://sendly.live/whatsapp/connect?token=placeholder",
                      "status": "initiated"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `invalid_phone_number`: `phoneNumber` is not a phone number.\n- `number_not_eligible`: The number is not active yet, or is a hosted-SMS number.\n- `invalid_request`: With `businessAccountId`: it is not a string, `verificationMethod` is not `sms` or `voice`, or `displayName` is not a string of at most 512 characters.\n- `display_name_required`: With `businessAccountId`: no display name was given, and the account has none to reuse.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_phone_number"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_phone_number",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_phone_number"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_not_eligible"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_not_eligible",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_not_eligible"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "display_name_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "display_name_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "display_name_required"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "402": {
            "description": "Payment Required.\n\n- `payment_method_required`, `payment_failed`: The account has no card on file (`payment_method_required`), or charging it failed (`payment_failed`). The signup is failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "payment_method_required",
                        "payment_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "actionUrl": {
                      "type": "string",
                      "enum": [
                        "/billing"
                      ]
                    },
                    "feature": {
                      "type": "string",
                      "enum": [
                        "whatsapp"
                      ]
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "actionUrl",
                    "feature"
                  ],
                  "title": "The $9.99 connection fee was not paid",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "payment_method_required",
                    "payment_failed"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to connect a number to WhatsApp, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot connect WhatsApp senders."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `number_not_found`: The number is not in this workspace.\n- `whatsapp_business_account_not_found`: With `businessAccountId`: the workspace has no connected account with this id and an active sender.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_not_found"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_business_account_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_business_account_not_found",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_business_account_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `number_pending_release`: The number is scheduled for release.\n- `messaging_activating`, `messaging_exception`: Messaging on this ported number is still activating, or its activation failed.\n- `toll_free_verification_required`: The toll-free number cannot receive texts until its toll-free verification is approved.\n- `whatsapp_already_enabled`: The number is already connected.\n- `signup_not_active`: With `businessAccountId`: the signup finished or failed while the fee was being taken, before the code was asked for.\n- `whatsapp_verification_in_progress`, `whatsapp_signup_in_progress`: Another signup for the number is in progress: one adding it by code (`whatsapp_verification_in_progress`), or a Facebook one when adding by code (`whatsapp_signup_in_progress`).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_pending_release"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_pending_release",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_pending_release"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "messaging_activating",
                            "messaging_exception"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "messaging_activating, messaging_exception",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "messaging_activating",
                        "messaging_exception"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "toll_free_verification_required"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "toll_free_verification_required",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "toll_free_verification_required"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_already_enabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_already_enabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_already_enabled"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSignupNotActiveError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_verification_in_progress",
                            "whatsapp_signup_in_progress"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "id": {
                          "type": "string",
                          "description": "The signup in progress. Absent when a stale number addition could not be cleared."
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "A signup for the number is in progress",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_verification_in_progress",
                        "whatsapp_signup_in_progress"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `whatsapp_verification_start_failed`: With `businessAccountId`: WhatsApp refused to send the code. The signup is failed and the fee refunded.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/DisposableEmailError"
                    },
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppVerificationStartFailedError"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.\n- `whatsapp_signup_limit_reached`: Five signups failed, or 20 were cancelled, in the last 24 hours.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_signup_limit_reached"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_signup_limit_reached",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_signup_limit_reached"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The signup or the fee failed unexpectedly. A fee already taken is refunded.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_verification_start_failed`: With `businessAccountId`: WhatsApp could not be asked for the code. The signup is failed and the fee refunded.\n- `whatsapp_unavailable`: Without `businessAccountId`: WhatsApp connections are switched off for now. Nothing was charged. `Retry-After` is sent too.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WhatsAppVerificationStartFailedError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_unavailable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "retryAfter": {
                          "type": "integer",
                          "description": "Seconds to wait: 3600."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "retryAfter"
                      ],
                      "title": "whatsapp_unavailable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_unavailable"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/signup/{id}": {
      "get": {
        "operationId": "getWhatsAppSignup",
        "summary": "Get a WhatsApp signup",
        "description": "Returns a signup of this workspace, to poll until it is `active` or `failed`.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.signup",
          "method": "get"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The signup's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSignup: The signup.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSignup"
                },
                "examples": {
                  "default": {
                    "summary": "A signup of the mock workspace that failed when nobody finished the connect page.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "status": "failed",
                      "phoneNumber": "+15555550101",
                      "businessAccountId": null,
                      "failureReasons": [
                        "signup_abandoned"
                      ],
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:read). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `signup_not_found`: No signup with this id belongs to the workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSignupNotFoundError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no signup.",
                    "value": {
                      "error": "signup_not_found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/signup/{id}/cancel": {
      "post": {
        "operationId": "cancelWhatsAppSignup",
        "summary": "Cancel a WhatsApp signup",
        "description": "Cancels a signup that is still `initiated`, `registering` or `verifying`. It fails with `cancelled_by_user`, any connection fee is refunded, and the number can be connected again straight away. Cancelling a signup that already failed changes nothing and answers 200.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The signup's id, from `POST /api/v1/whatsapp/signup`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSignup: The signup is cancelled, now or already, or it had already failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSignup"
                },
                "examples": {
                  "default": {
                    "summary": "A signup in progress is cancelled. Built from cancelWhatsappSignup, not captured: the route is new.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000001",
                      "status": "failed",
                      "phoneNumber": "+15555550100",
                      "businessAccountId": null,
                      "failureReasons": [
                        "cancelled_by_user"
                      ],
                      "updatedAt": "2026-10-17T12:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key tried to cancel a signup, which needs a live key. Built from waLiveKeyRequired, not captured: the route is new.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot cancel WhatsApp connections."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `signup_not_found`: No signup with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "signup_not_found"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "No such signup",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "signup_not_found"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `whatsapp_already_enabled`: The signup finished and the number is connected. Disconnect the sender instead.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "whatsapp_already_enabled"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "whatsapp_already_enabled",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "whatsapp_already_enabled"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The signup could not be cancelled. It is still in progress.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/signup/{id}/resend": {
      "post": {
        "operationId": "resendWhatsAppSignupCode",
        "summary": "Send a number's WhatsApp code again",
        "description": "Asks WhatsApp to send a new code to a number being added by code, at most every 30 seconds.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.signup",
          "method": "resend"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The signup's id, from `POST /api/v1/whatsapp/signup`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "How to send the code.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResendWhatsAppSignupCodeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSignup: A new code is on its way, or the number is already connected.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSignup"
                },
                "examples": {
                  "default": {
                    "summary": "A new code asked for by voice call, after one wrong code. Built from resendWhatsappNumberCode, not captured: it needs a live key and has WhatsApp call a real number.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "status": "verifying",
                      "phoneNumber": "+15555550100",
                      "businessAccountId": "100000000000001",
                      "failureReasons": null,
                      "verificationMethod": "voice",
                      "verificationAttemptsRemaining": 4,
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `verificationMethod` is not `sms` or `voice`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked for another verification code, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot connect WhatsApp senders."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `signup_not_found`: No signup with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSignupNotFoundError"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `signup_not_active`: The signup is not waiting for a code, or was started more than 3 hours ago.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSignupNotActiveError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.\n- `whatsapp_verification_resend_failed`: WhatsApp would not send another code yet.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/DisposableEmailError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppVerificationResendFailedError"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.\n- `whatsapp_verification_resend_too_soon`: The last code was asked for less than 30 seconds ago. `Retry-After` is sent too.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_verification_resend_too_soon"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "retryAfter": {
                          "type": "integer",
                          "description": "Seconds to wait."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "retryAfter"
                      ],
                      "title": "whatsapp_verification_resend_too_soon",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_verification_resend_too_soon"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_verification_resend_failed`: WhatsApp could not be reached, or failed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppVerificationResendFailedError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/signup/{id}/verify": {
      "post": {
        "operationId": "verifyWhatsAppSignup",
        "summary": "Send a number's WhatsApp code",
        "description": "Sends the 6-digit code WhatsApp sent to a number being added by code. A right code connects the number. After 5 wrong codes the signup fails and its fee is refunded.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.signup",
          "method": "verify"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The signup's id, from `POST /api/v1/whatsapp/signup`."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The code.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyWhatsAppSignupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppSignup: The number is connected, now or already.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppSignup"
                },
                "examples": {
                  "default": {
                    "summary": "The right code: the number is connected. Built from submitWhatsappNumberCode, not captured: it needs a live key and a code WhatsApp sent to a real number.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000101",
                      "status": "active",
                      "phoneNumber": "+15555550100",
                      "businessAccountId": "100000000000001",
                      "failureReasons": null,
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_verification_code`: `code` is not 6 digits once spaces and dashes are dropped.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_verification_code"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_verification_code",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_verification_code"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `settings:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key sent a verification code, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot connect WhatsApp senders."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `signup_not_found`: No signup with this id belongs to the workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSignupNotFoundError"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `signup_not_active`: The signup is not waiting for a code, or was started more than 3 hours ago.\n- `whatsapp_verification_failed`: Too many wrong codes. The signup is failed and the fee refunded.\n- `whatsapp_verification_busy`: Another code for this signup is being checked.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WhatsAppSignupNotActiveError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_verification_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_verification_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_verification_failed"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_verification_busy"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_verification_busy",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_verification_busy"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.\n- `whatsapp_verification_code_invalid`: WhatsApp did not accept the code.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/DisposableEmailError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_verification_code_invalid"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "attemptsRemaining": {
                          "type": "integer",
                          "description": "Wrong codes left."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "attemptsRemaining"
                      ],
                      "title": "whatsapp_verification_code_invalid",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_verification_code_invalid"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `whatsapp_verification_unavailable`: WhatsApp could not check the code. The attempt is not counted.\n- `whatsapp_activation_pending`: WhatsApp accepted the code, but connecting the number did not finish.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_verification_unavailable"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_verification_unavailable",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_verification_unavailable"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "whatsapp_activation_pending"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "whatsapp_activation_pending",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "whatsapp_activation_pending"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/templates": {
      "get": {
        "operationId": "listWhatsAppTemplates",
        "summary": "List WhatsApp templates",
        "description": "Lists the workspace's templates, newest first, as Sendly last synced them from WhatsApp (every 15 minutes). Templates of a WhatsApp Business account that is disconnected are left out.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.templates",
          "method": "list"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppTemplateList: The templates.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppTemplateList"
                },
                "examples": {
                  "default": {
                    "summary": "The mock workspace's one approved template.",
                    "value": {
                      "templates": [
                        {
                          "id": "00000000-0000-4000-8000-000000000002",
                          "name": "order_update_e2e",
                          "language": "en",
                          "category": "UTILITY",
                          "status": "APPROVED",
                          "body": "Your order {{1}} has shipped.",
                          "header": null,
                          "footer": null,
                          "examples": {
                            "1": "A1234"
                          },
                          "qualityRating": null,
                          "rejectionReason": null,
                          "createdAt": "2026-01-01T00:00:00.000Z",
                          "updatedAt": "2026-01-01T00:00:00.000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "No Authorization header.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:read). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWhatsAppTemplate",
        "summary": "Create a WhatsApp template",
        "description": "Submits a template to WhatsApp for review, which usually takes 24 to 48 hours. It starts `PENDING`.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": true,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.templates",
          "method": "create"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7E]+$",
              "description": "Send the same key again to get the stored answer instead of a second run, for 24 hours. 1 to 255 printable ASCII characters. `X-Idempotency-Key` is read too. 2xx and 4xx answers are stored, except 429; a 5xx or a 429 is not, so a retry with the same key runs again."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "description": "The template.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWhatsAppTemplateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.\n\n- WhatsAppTemplateCreated: The template was submitted for review.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppTemplateCreated"
                },
                "examples": {
                  "default": {
                    "summary": "A template submitted for review from a sender whose display name is not approved yet. Built from createWaTemplate, not captured: it needs a live key and submits the template to WhatsApp.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000102",
                      "name": "order_shipped",
                      "language": "en_US",
                      "category": "UTILITY",
                      "status": "PENDING",
                      "body": "Your order {{1}} has shipped.",
                      "header": null,
                      "footer": null,
                      "examples": {
                        "1": "A1234"
                      },
                      "qualityRating": null,
                      "rejectionReason": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z",
                      "warnings": [
                        "This sender's display name isn't approved yet. Templates are far more likely to be rejected until it is."
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_idempotency_key`: The Idempotency-Key is longer than 255 characters or not printable ASCII.\n- `template_language_required`: `language` is missing or blank.\n- `template_name_invalid`, `template_name_reserved_prefix`, `template_category_invalid`, `template_body_required`, `template_header_variable_unsupported`, `template_example_required`, `template_authentication_no_links`, `template_authentication_otp_button_required`, `template_button_url_required`, `template_button_type_unsupported`, `template_body_too_long`, `template_body_variable_at_edge`, `template_footer_too_long`, `template_too_many_buttons`, `template_button_text_too_long`: The template breaks one of WhatsApp's rules.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidIdempotencyKeyError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "template_language_required"
                          ]
                        }
                      },
                      "required": [
                        "error"
                      ],
                      "description": "Only `error`, with no `message`.",
                      "title": "template_language_required",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "template_language_required"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppTemplateRuleError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `templates:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to submit a template, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot manage templates."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `whatsapp_sender_not_connected`: The number is not an active WhatsApp sender of this workspace.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppSenderNotConnectedError"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `template_already_exists`: The business account has a template with this name and language.\n- `template_name_locked`: A template with this name and language was deleted less than 30 days ago. Edit a template instead.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WhatsAppTemplateExistsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "template_name_locked"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "suggestion": {
                          "type": "string",
                          "enum": [
                            "edit instead"
                          ]
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "suggestion"
                      ],
                      "title": "template_name_locked",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "template_name_locked"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.\n- `idempotency_key_mismatch`: The Idempotency-Key was already used with a different body.\n- `template_refused`: WhatsApp refused the template. Change it before sending it again.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/DisposableEmailError"
                    },
                    {
                      "$ref": "#/components/schemas/IdempotencyKeyMismatchError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppTemplateRefusedError"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `template_create_failed`: WhatsApp could not be reached or did not answer. Safe to retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "template_create_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "template_create_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "template_create_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/templates/{id}": {
      "patch": {
        "operationId": "updateWhatsAppTemplate",
        "summary": "Edit a WhatsApp template",
        "description": "Changes an `APPROVED` or `REJECTED` template and sends it back for review, as `PENDING`. Fields left out keep their value. Its name, language and category cannot change.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.templates",
          "method": "update"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The template's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWhatsAppTemplateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppTemplate: The template, sent back for review.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppTemplate"
                },
                "examples": {
                  "default": {
                    "summary": "A rejected template with a footer added, sent back for review. Built from updateWaTemplate, not captured: it needs a live key and resubmits the template to WhatsApp.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000102",
                      "name": "order_shipped",
                      "language": "en_US",
                      "category": "UTILITY",
                      "status": "PENDING",
                      "body": "Your order {{1}} has shipped.",
                      "header": null,
                      "footer": "Reply STOP to opt out",
                      "examples": {
                        "1": "A1234"
                      },
                      "qualityRating": null,
                      "rejectionReason": null,
                      "createdAt": "2026-01-01T00:00:00.000Z",
                      "updatedAt": "2026-01-01T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `template_name_invalid`, `template_name_reserved_prefix`, `template_category_invalid`, `template_body_required`, `template_header_variable_unsupported`, `template_example_required`, `template_authentication_no_links`, `template_authentication_otp_button_required`, `template_button_url_required`, `template_button_type_unsupported`, `template_body_too_long`, `template_body_variable_at_edge`, `template_footer_too_long`, `template_too_many_buttons`, `template_button_text_too_long`: The edited template breaks one of WhatsApp's rules.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppTemplateRuleError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `templates:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to edit a template, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot manage templates."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `template_not_found`: No template with this id belongs to the workspace, or it was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppTemplateNotFoundError"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `template_not_editable`: The template is neither `APPROVED` nor `REJECTED`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "template_not_editable"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "templateStatus": {
                      "type": "string",
                      "description": "The template's review status, as WhatsApp reports it, in upper case. Only an `APPROVED` template can be sent. Known values: `PENDING`, `APPROVED`, `REJECTED`, `PAUSED`, `DISABLED`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "PENDING",
                        "APPROVED",
                        "REJECTED",
                        "PAUSED",
                        "DISABLED"
                      ]
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "templateStatus"
                  ],
                  "title": "template_not_editable",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "template_not_editable"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.\n- `template_refused`: WhatsApp refused the change. Change it before sending it again.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/DisposableEmailError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppTemplateRefusedError"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `template_update_failed`: WhatsApp could not be reached or did not answer. Safe to retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "template_update_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "template_update_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "template_update_failed"
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWhatsAppTemplate",
        "summary": "Delete a WhatsApp template",
        "description": "Deletes a template. WhatsApp keeps its name and language from being reused for 30 days.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:write"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": true,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp.templates",
          "method": "delete"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The template's id."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppTemplateDeleted: The template is deleted, even when WhatsApp could not be told.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppTemplateDeleted"
                },
                "examples": {
                  "default": {
                    "summary": "The template is deleted. Built from deleteWaTemplate, not captured: it needs a live key and deletes the template on WhatsApp.",
                    "value": {
                      "id": "00000000-0000-4000-8000-000000000102",
                      "deleted": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:write). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.\n- `insufficient_permissions`: In a team workspace, the caller's role lacks the `templates:write` permission.\n- `whatsapp_requires_live_key`: A test API key called it. WhatsApp changes need a live key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppLiveKeyRequiredError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "A test key asked to delete a template, which needs a live key.",
                    "value": {
                      "error": "whatsapp_requires_live_key",
                      "message": "WhatsApp requires a live API key. Test keys cannot manage templates."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.\n- `template_not_found`: No template with this id belongs to the workspace, or it was deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BareNotFoundError"
                    },
                    {
                      "$ref": "#/components/schemas/WhatsAppTemplateNotFoundError"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.\n- `rate_limit_exceeded`: An API key has used its requests for this minute: 60 for a test key, 600 for a live key. A CLI or dashboard session is not limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationThrottledError"
                    },
                    {
                      "$ref": "#/components/schemas/RateLimitError"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `internal_error`: The request failed unexpectedly.\n- `server_error`: The request failed unexpectedly.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/BareInternalError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/whatsapp/window": {
      "get": {
        "operationId": "getWhatsAppWindow",
        "summary": "Check the 24-hour window",
        "description": "Says whether the 24-hour customer-service window between a sender and a recipient is open, from Sendly's record of the recipient's last message. Inside the window any message can be sent; outside it, only a template.",
        "tags": [
          "WhatsApp channel"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [
          "whatsapp:read"
        ],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "whatsapp",
          "method": "window"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The WhatsApp sender, in E.164 format."
            },
            "required": true,
            "name": "from",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The recipient, in E.164 format."
            },
            "required": true,
            "name": "to",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WhatsAppWindow: The window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppWindow"
                },
                "examples": {
                  "default": {
                    "summary": "A sender and recipient with no window on record.",
                    "value": {
                      "open": false,
                      "expiresAt": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_request`: `from` or `to` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "`to` is missing.",
                    "value": {
                      "error": "invalid_request",
                      "message": "Query params 'from' and 'to' are required"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `insufficient_permissions`: An API key lacks a required scope (whatsapp:read). A CLI or dashboard session skips this check.\n- Not a workspace member: The `X-Organization-Id` header or `_orgId` query parameter names a workspace the caller is not an active member of, or an API key's own workspace no longer has its owner as an active member.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationMembershipError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `not_found`: WhatsApp is not enabled for the account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BareNotFoundError"
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- Workspace lookup failed: The workspace could not be looked up.\n- `server_error`: The request failed unexpectedly.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/OrganizationContextError"
                    },
                    {
                      "$ref": "#/components/schemas/ServerError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{id}/upgrade": {
      "post": {
        "operationId": "startWorkspaceUpgrade",
        "summary": "Start a business entity upgrade",
        "description": "Moves a verified workspace to a new legal entity, such as a sole proprietor that formed an LLC. The new entity gets its own toll-free number and verification, set up in the background; the current number keeps sending until the new one is approved, typically in 1 to 2 weeks. Poll `GET /api/v1/workspaces/{id}/upgrade/status`. The submission is checked first: fixable problems, such as a 2-letter state code, are corrected, and anything the carrier would refuse answers 422. Behind the `entity_upgrade_enabled` flag. Only the workspace's owner can call it, with an API key, CLI session or dashboard session. An API key must belong to that workspace (a key made without a workspace counts as its personal workspace's), unless it is an enterprise master key. Changing an upgrade needs a live key with the `numbers:write` scope, or an enterprise master key.",
        "tags": [
          "Business entity upgrade"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "businessUpgrade",
          "method": "start"
        },
        "x-sendly-visibility": "preview",
        "x-stability-level": "alpha",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. The caller must own it."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The new business entity.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartWorkspaceUpgradeRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted.\n\n- WorkspaceUpgradeStarted: The upgrade was recorded and is being set up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceUpgradeStarted"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the upgrade is recorded and set up in the background. Not captured, since a real start buys a number and submits a registration.",
                    "value": {
                      "success": true,
                      "pendingVerificationId": "00000000-0000-4000-8000-000000000101",
                      "status": "provisioning",
                      "message": "Your business entity upgrade is being provisioned. Your current number stays active until the new one is approved (typically 1-2 weeks)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_upload`: A file in a field other than `einDoc`, a second file, a text field over 1 MB, or a malformed body such as one without a boundary.\n- `missing_required_fields`: `businessName`, `brn`, `brnType`, `brnCountry` or `entityType` is missing or empty.\n- `active_verification_not_verified`: The workspace's current verification is not `verified` yet. `message` names its status as stored.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidUploadError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "missing_required_fields"
                          ]
                        },
                        "required": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "businessName",
                              "brn",
                              "brnType",
                              "brnCountry",
                              "entityType"
                            ]
                          },
                          "description": "Every required field, whichever were missing."
                        }
                      },
                      "required": [
                        "error",
                        "required"
                      ],
                      "description": "No `message`: `required` lists the fields the request needs.",
                      "title": "missing_required_fields",
                      "x-sendly-error-shape": "bare",
                      "x-sendly-error-codes": [
                        "missing_required_fields"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "active_verification_not_verified"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "active_verification_not_verified",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "active_verification_not_verified"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the new entity's required fields are missing. Not captured, since it needs a workspace with the upgrade flag on.",
                    "value": {
                      "error": "missing_required_fields",
                      "required": [
                        "businessName",
                        "brn",
                        "brnType",
                        "brnCountry",
                        "entityType"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `forbidden`: An API key that is not an enterprise master key is bound to another workspace than the one in the path. A key made without a workspace counts as its personal workspace's key.\n- `live_key_required`: A test API key called it: changing an upgrade needs a live key.\n- `insufficient_permissions`: An API key that is not an enterprise master key lacks the `numbers:write` scope.\n- `forbidden`: The caller does not own the workspace. A team member, even an admin, gets this too.\n- `feature_disabled`: Entity upgrades are not enabled for the caller's account.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "feature_disabled"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "feature_disabled",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "feature_disabled"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.\n- `no_active_verification`: The workspace has no current verification to upgrade from.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_active_verification"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "no_active_verification",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_active_verification"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no workspace.",
                    "value": {
                      "error": "workspace_not_found",
                      "message": "Workspace not found."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `upgrade_in_progress`: The workspace already has an upgrade pending.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "upgrade_in_progress"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "pendingVerificationId": {
                      "type": "string",
                      "description": "The upgrade already pending."
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "pendingVerificationId"
                  ],
                  "title": "upgrade_in_progress",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "upgrade_in_progress"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.\n- `file_too_large`: A file over 10 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyTooLargeError"
                    },
                    {
                      "$ref": "#/components/schemas/FileTooLargeError"
                    }
                  ]
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.\n- `unsupported_media_type`: A file that is not a PDF, PNG, JPEG, WEBP or HEIC image (`Only PDF or image files are allowed`).",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyEncodingError"
                    },
                    {
                      "$ref": "#/components/schemas/UnsupportedMediaTypeError"
                    }
                  ]
                },
                "examples": {
                  "wrong-type": {
                    "summary": "Built from the code: since #234 the last error handler answers an upload middleware's refusal with a 4xx that says why, not a 500 `Internal Server Error`. The production capture of 2026-10-02 predates that change. It was: A multipart body whose einDoc is a text file, refused by the upload parser before the handler runs.",
                    "value": {
                      "error": "unsupported_media_type",
                      "message": "Only PDF or image files are allowed"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.\n- `submission_invalid`: The submission has problems the carrier would refuse it for.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/DisposableEmailError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "submission_invalid"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "blockers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "severity": {
                                "type": "string",
                                "enum": [
                                  "blocker"
                                ]
                              },
                              "field": {
                                "type": "string",
                                "description": "The field the problem is in, named as the carrier's submission names it, such as `businessRegistrationNumber`, `businessState` or `productionMessageContent`, not as the request does."
                              },
                              "code": {
                                "type": "string",
                                "description": "What is wrong. Known values: `brn_format_invalid`, `ein_format_invalid`, `entity_type_mismatch`, `field_not_in_enum`, `field_pattern_mismatch`, `field_required`, `field_too_long`, `phone_missing_plus`, `phone_not_e164`, `registry_inactive`, `registry_name_mismatch`, `registry_no_match`, `samples_missing_stop`, `sole_prop_no_brn`, `sole_prop_with_brn_will_be_cleared`, `ssn_format_invalid`, `state_must_be_full_name`, `state_unrecognized`. More can be added at any time, so treat an unknown value as valid.",
                                "x-sendly-extensible-enum": [
                                  "brn_format_invalid",
                                  "ein_format_invalid",
                                  "entity_type_mismatch",
                                  "field_not_in_enum",
                                  "field_pattern_mismatch",
                                  "field_required",
                                  "field_too_long",
                                  "phone_missing_plus",
                                  "phone_not_e164",
                                  "registry_inactive",
                                  "registry_name_mismatch",
                                  "registry_no_match",
                                  "samples_missing_stop",
                                  "sole_prop_no_brn",
                                  "sole_prop_with_brn_will_be_cleared",
                                  "ssn_format_invalid",
                                  "state_must_be_full_name",
                                  "state_unrecognized"
                                ]
                              },
                              "message": {
                                "type": "string"
                              },
                              "suggestion": {
                                "type": "string",
                                "description": "How to fix it, when there is a fix."
                              }
                            },
                            "required": [
                              "severity",
                              "field",
                              "code",
                              "message"
                            ]
                          },
                          "description": "What has to change before the submission can go, after the automatic fixes."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "blockers"
                      ],
                      "title": "submission_invalid",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "submission_invalid"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: an EIN that is not 9 digits blocks the submission.",
                    "value": {
                      "error": "submission_invalid",
                      "message": "This submission has carrier-blocking issues that must be fixed before we can send it. We auto-corrected what we could; please fix the rest.",
                      "blockers": [
                        {
                          "severity": "blocker",
                          "field": "businessRegistrationNumber",
                          "code": "ein_format_invalid",
                          "message": "The EIN must be 9 digits.",
                          "suggestion": "Enter it as 12-3456789 or 123456789."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `ein_doc_upload_failed`: The registration document could not be stored.\n- `insert_failed`: The upgrade could not be recorded.\n- `internal_error`: Something failed unexpectedly, as when a second start races the first past the pending-upgrade check. `message` is the underlying error's own text.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "ein_doc_upload_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "ein_doc_upload_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "ein_doc_upload_failed"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "insert_failed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "insert_failed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "insert_failed"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `enqueue_failed`: The background setup could not be started. Nothing was kept, so the request can be retried.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "enqueue_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "enqueue_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "enqueue_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{id}/upgrade/cancel": {
      "post": {
        "operationId": "cancelWorkspaceUpgrade",
        "summary": "Cancel a business entity upgrade",
        "description": "Removes the workspace's pending upgrade: its reserved toll-free number is released, and its messaging profile and stored registration document are deleted, all in the background. The current verification and number are untouched. With nothing pending it answers 200 with `cancelled: false`. While the new number is still being set up it answers 409, for up to 30 minutes. Only the workspace's owner can call it, with an API key, CLI session or dashboard session. An API key must belong to that workspace (a key made without a workspace counts as its personal workspace's), unless it is an enterprise master key. Changing an upgrade needs a live key with the `numbers:write` scope, or an enterprise master key.",
        "tags": [
          "Business entity upgrade"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "businessUpgrade",
          "method": "cancel"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. The caller must own it."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- Upgrade cancelled: The pending upgrade was removed.\n- No upgrade to cancel: The workspace has no pending upgrade.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceUpgradeCancelled"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceUpgradeNothingToCancel"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the pending upgrade is removed. Not captured, since a real cancel releases a number.",
                    "value": {
                      "success": true,
                      "cancelled": true,
                      "cancelledVerificationId": "00000000-0000-4000-8000-000000000101",
                      "message": "Upgrade cancelled. Your existing toll-free number is unchanged."
                    }
                  },
                  "nothing-pending": {
                    "summary": "Built from the handler: a workspace with no pending upgrade.",
                    "value": {
                      "success": true,
                      "cancelled": false,
                      "message": "No pending upgrade to cancel."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `forbidden`: An API key that is not an enterprise master key is bound to another workspace than the one in the path. A key made without a workspace counts as its personal workspace's key.\n- `live_key_required`: A test API key called it: changing an upgrade needs a live key.\n- `insufficient_permissions`: An API key that is not an enterprise master key lacks the `numbers:write` scope.\n- `forbidden`: The caller does not own the workspace. A team member, even an admin, gets this too.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no workspace.",
                    "value": {
                      "error": "workspace_not_found",
                      "message": "Workspace not found."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `upgrade_provisioning`: The pending upgrade is `provisioning` and changed less than 30 minutes ago: its new number is still being set up.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "upgrade_provisioning"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "upgrade_provisioning",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "upgrade_provisioning"
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: Cancelling failed unexpectedly. `message` is the underlying error's own text.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{id}/upgrade/disposition": {
      "post": {
        "operationId": "setWorkspaceUpgradeDisposition",
        "summary": "Choose what happens to the previous number",
        "description": "After an upgrade is approved, records what happens to the previous entity's toll-free number. `moved` only records the choice, after checking you own `targetOrgId`, which is not stored. `released` releases the number at the carrier before answering, unless another workspace still uses it. It applies to the workspace's most recently superseded entity, and is recorded once: a second choice answers 409. Only the workspace's owner can call it, with an API key, CLI session or dashboard session. An API key must belong to that workspace (a key made without a workspace counts as its personal workspace's), unless it is an enterprise master key. Changing an upgrade needs a live key with the `numbers:write` scope, or an enterprise master key.",
        "tags": [
          "Business entity upgrade"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "businessUpgrade",
          "method": "setDisposition"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. The caller must own it."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "What to do with the previous number.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkspaceUpgradeDispositionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WorkspaceUpgradeDisposition: The choice was recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceUpgradeDisposition"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the previous number stays on another workspace. Not captured, since it changes a real registration's record.",
                    "value": {
                      "success": true,
                      "disposition": "moved",
                      "supersededVerificationId": "00000000-0000-4000-8000-000000000102",
                      "message": "Your previous number stays active under your chosen workspace."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_disposition`: `disposition` is not `moved` or `released`.\n- `missing_target`: `disposition` is `moved` and `targetOrgId` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "invalid_disposition"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "invalid_disposition",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "invalid_disposition"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "missing_target"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "missing_target",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "missing_target"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `forbidden`: An API key that is not an enterprise master key is bound to another workspace than the one in the path. A key made without a workspace counts as its personal workspace's key.\n- `live_key_required`: A test API key called it: changing an upgrade needs a live key.\n- `insufficient_permissions`: An API key that is not an enterprise master key lacks the `numbers:write` scope.\n- `forbidden`: The caller does not own the workspace. A team member, even an admin, gets this too.\n- `target_not_owned`: `targetOrgId` names a workspace the caller does not own.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "target_not_owned"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "target_not_owned",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "target_not_owned"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.\n- `no_superseded_verification`: The workspace has no superseded entity.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_superseded_verification"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "no_superseded_verification",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_superseded_verification"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no workspace.",
                    "value": {
                      "error": "workspace_not_found",
                      "message": "Workspace not found."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict.\n\n- `already_disposed`: A choice for the previous number is already recorded.\n- `number_in_use`: `disposition` is `released` and another workspace still uses the previous number. Choose `moved` instead.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "already_disposed"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "disposition": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "enum": [
                            "moved",
                            "released",
                            null
                          ],
                          "description": "The choice already recorded, or `null` when another request recorded one at the same moment."
                        }
                      },
                      "required": [
                        "error",
                        "message",
                        "disposition"
                      ],
                      "title": "already_disposed",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "already_disposed"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "number_in_use"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "number_in_use",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "number_in_use"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The choice could not be recorded. `message` is the underlying error's own text.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `release_failed`: The carrier did not release the previous number. Nothing is recorded, so the choice can be made again.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "release_failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ],
                  "title": "release_failed",
                  "x-sendly-error-shape": "envelope",
                  "x-sendly-error-codes": [
                    "release_failed"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{id}/upgrade/resubmit": {
      "post": {
        "operationId": "resubmitWorkspaceUpgrade",
        "summary": "Resubmit a business entity upgrade",
        "description": "Updates the pending upgrade with the fields sent and sends it back to the carrier for review, whatever its status. The upgrade's status becomes `processing` and its rejection reason is cleared; if the carrier refuses the update, it becomes `rejected` and the call answers 503. Only the workspace's owner can call it, with an API key, CLI session or dashboard session. An API key must belong to that workspace (a key made without a workspace counts as its personal workspace's), unless it is an enterprise master key. Changing an upgrade needs a live key with the `numbers:write` scope, or an enterprise master key.",
        "tags": [
          "Business entity upgrade"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "businessUpgrade",
          "method": "resubmit"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. The caller must own it."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "description": "The fields to change.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResubmitWorkspaceUpgradeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.\n\n- WorkspaceUpgradeResubmitted: The carrier took the update.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceUpgradeResubmitted"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the carrier took the update. Not captured, since a real resubmit changes a registration.",
                    "value": {
                      "success": true,
                      "pendingVerificationId": "00000000-0000-4000-8000-000000000101",
                      "message": "Resubmitted to the carrier. Typical review 1-2 weeks."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: The body is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.\n- `invalid_upload`: A file in a field other than `einDoc`, a second file, a text field over 1 MB, or a malformed body such as one without a boundary.\n- `pending_never_submitted`: The pending upgrade never reached the carrier. Cancel it and start again.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidUploadError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "pending_never_submitted"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "pending_never_submitted",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "pending_never_submitted"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `forbidden`: An API key that is not an enterprise master key is bound to another workspace than the one in the path. A key made without a workspace counts as its personal workspace's key.\n- `live_key_required`: A test API key called it: changing an upgrade needs a live key.\n- `insufficient_permissions`: An API key that is not an enterprise master key lacks the `numbers:write` scope.\n- `forbidden`: The caller does not own the workspace. A team member, even an admin, gets this too.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    },
                    {
                      "$ref": "#/components/schemas/LiveKeyRequiredError"
                    },
                    {
                      "$ref": "#/components/schemas/InsufficientPermissionsError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.\n- `no_pending_upgrade`: The workspace has no pending upgrade.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceNotFoundError"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "no_pending_upgrade"
                          ]
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "error",
                        "message"
                      ],
                      "title": "no_pending_upgrade",
                      "x-sendly-error-shape": "envelope",
                      "x-sendly-error-codes": [
                        "no_pending_upgrade"
                      ]
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no workspace.",
                    "value": {
                      "error": "workspace_not_found",
                      "message": "Workspace not found."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: The body is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.\n- `file_too_large`: A file over 10 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyTooLargeError"
                    },
                    {
                      "$ref": "#/components/schemas/FileTooLargeError"
                    }
                  ]
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: The body declares a charset or content encoding the server cannot read.\n- `unsupported_media_type`: A file that is not a PDF, PNG, JPEG, WEBP or HEIC image (`Only PDF or image files are allowed`).",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyEncodingError"
                    },
                    {
                      "$ref": "#/components/schemas/UnsupportedMediaTypeError"
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: Resubmitting failed unexpectedly, as when a replacement document could not be stored. `message` is the underlying error's own text.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable.\n\n- `resubmit_failed`: The carrier refused the update. The upgrade is now `rejected`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "resubmit_failed"
                      ]
                    },
                    "details": {
                      "type": "string",
                      "description": "The carrier client's error, such as the carrier's reason for refusing the update."
                    },
                    "pendingVerificationId": {
                      "type": "string",
                      "description": "The pending verification, now `rejected`."
                    }
                  },
                  "required": [
                    "error",
                    "details",
                    "pendingVerificationId"
                  ],
                  "description": "No `message`: `details` says why.",
                  "title": "resubmit_failed",
                  "x-sendly-error-shape": "bare",
                  "x-sendly-error-codes": [
                    "resubmit_failed"
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: the carrier refused the update, so the upgrade is now rejected.",
                    "value": {
                      "error": "resubmit_failed",
                      "details": "The business name does not match the registration.",
                      "pendingVerificationId": "00000000-0000-4000-8000-000000000101"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{id}/upgrade/status": {
      "get": {
        "operationId": "getWorkspaceUpgradeStatus",
        "summary": "Get a business entity upgrade's status",
        "description": "Returns the workspace's upgrade in flight, or `null`. The current verification is not part of it. Only the workspace's owner can call it, with an API key, CLI session or dashboard session. An API key must belong to that workspace (a key made without a workspace counts as its personal workspace's), unless it is an enterprise master key.",
        "tags": [
          "Business entity upgrade"
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "x-sendly-auth": "cliOrApiKey",
        "x-sendly-scopes": [],
        "x-sendly-idempotent": false,
        "x-sendly-rate-limited": false,
        "x-sendly-pagination": "none",
        "x-sendly-sdk": {
          "resource": "businessUpgrade",
          "method": "status"
        },
        "x-sendly-visibility": "public",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The workspace's id. The caller must own it."
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.\n\n- WorkspaceUpgradeStatus: The pending upgrade, or `null`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceUpgradeStatus"
                },
                "examples": {
                  "default": {
                    "summary": "Built from the handler: an upgrade under carrier review. Not captured, since no workspace the test key can reach has one.",
                    "value": {
                      "pending": {
                        "id": "00000000-0000-4000-8000-000000000101",
                        "businessName": "Example Holdings LLC",
                        "status": "processing",
                        "entityType": "PRIVATE_PROFIT",
                        "brnType": "EIN",
                        "brnCountry": "US",
                        "tollFreeNumber": "+15555550101",
                        "rejectionReason": null,
                        "createdAt": "2026-01-01T00:00:00.000Z",
                        "updatedAt": "2026-01-01T00:00:00.000Z"
                      }
                    }
                  },
                  "none-pending": {
                    "summary": "Built from the handler: a workspace with no upgrade in flight.",
                    "value": {
                      "pending": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.\n\n- Unreadable request body: A body sent anyway is JSON that cannot be parsed, or JSON that is not an object or array.\n- `invalid_request`: An API key was passed in the URL (`api_key`, `apiKey` or `key`) instead of the Authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/RequestBodyError"
                    },
                    {
                      "$ref": "#/components/schemas/InvalidRequestError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.\n\n- `unauthorized`: No API key, CLI session or dashboard session was sent, an `sk_` key is malformed, unknown, revoked or expired, or a CLI session could not be checked.\n- `unauthorized`: The CLI session is invalid, expired or revoked.\n- `invalid_token`: The CLI session's user no longer exists.\n- Authentication failed: Checking the credentials failed unexpectedly, as when the key's workspace could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/SessionAuthenticationError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionInvalidError"
                    },
                    {
                      "$ref": "#/components/schemas/CliSessionUserGoneError"
                    },
                    {
                      "$ref": "#/components/schemas/AuthenticationFailedError"
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "An API key that does not exist.",
                    "value": {
                      "error": "unauthorized",
                      "message": "Invalid or missing credentials. Use: Authorization: Bearer sk_xxx"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.\n\n- `account_suspended`: The key's owner, or the signed-in user, is suspended.\n- `workspace_suspended`: The key's workspace belongs to a suspended owner.\n- `forbidden`: An API key that is not an enterprise master key is bound to another workspace than the one in the path. A key made without a workspace counts as its personal workspace's key.\n- `forbidden`: The caller does not own the workspace. A team member, even an admin, gets this too.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AccountSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspaceSuspendedError"
                    },
                    {
                      "$ref": "#/components/schemas/WorkspacePermissionError"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not Found.\n\n- `workspace_not_found`: No workspace has this id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceNotFoundError"
                },
                "examples": {
                  "default": {
                    "summary": "An id that matches no workspace.",
                    "value": {
                      "error": "workspace_not_found",
                      "message": "Workspace not found."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Content Too Large.\n\n- Request body too large: A body sent anyway is larger than 10 MB of JSON or 100 KB of form data, or has more than 1,000 form fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyTooLargeError"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported Media Type.\n\n- Unreadable request body encoding: A body sent anyway declares a charset or content encoding the server cannot read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestBodyEncodingError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content.\n\n- `disposable_email`: A dashboard session whose user signed up with a disposable email address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisposableEmailError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests.\n\n- `too_many_failed_key_attempts`, `too_many_concurrent_verifications`: Too many failed or concurrent key checks from this address.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationThrottledError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.\n\n- Unhandled server error: The handler or a middleware failed without answering itself.\n- `internal_error`: The upgrade could not be read. `message` is the underlying error's own text.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/UnhandledServerError"
                    },
                    {
                      "$ref": "#/components/schemas/InternalError"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {},
  "components": {
    "headers": {
      "IdempotencyReplayed": {
        "description": "`true` when this is the stored answer to an earlier request with the same Idempotency-Key, not a new run.",
        "schema": {
          "type": "string",
          "enum": [
            "true"
          ]
        }
      },
      "RateLimitLimit": {
        "description": "Requests allowed in the current window: a minute for an API key's limit.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitRemaining": {
        "description": "Requests left in the current window.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitReset": {
        "description": "Seconds until the current window's allowance resets.",
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "parameters": {},
    "schemas": {
      "Account": {
        "type": "object",
        "properties": {
          "user": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The user's id."
              },
              "email": {
                "type": "string"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "description": "When the user signed up. ISO 8601, in UTC."
              }
            },
            "required": [
              "id",
              "email",
              "createdAt"
            ]
          },
          "organization": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "The workspace's id, the `organization_id` webhook payloads carry."
              },
              "name": {
                "type": "string"
              },
              "isPersonal": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "name",
              "isPersonal"
            ],
            "description": "The workspace the key belongs to. `null` for a personal key."
          },
          "credits": {
            "type": "object",
            "properties": {
              "balance": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "enum": [
                      "0"
                    ]
                  }
                ],
                "description": "The balance of the workspace's own credits row, or the user's for a personal key. For a pooled enterprise workspace it is not the pool's balance, which `GET /api/v1/account/credits` returns. The string `\"0\"` when it is zero or the account has no balance yet, a number otherwise."
              },
              "reservedBalance": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "enum": [
                      "0"
                    ]
                  }
                ],
                "description": "Credits held for messages still being sent. The string `\"0\"` when it is zero or the account has no balance yet, a number otherwise."
              }
            },
            "required": [
              "balance",
              "reservedBalance"
            ]
          },
          "verification": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "status": {
                "type": "string",
                "description": "Where the business verification is. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `processing`, `action_required`, `verified`, `approved`, `rejected`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "pending",
                  "pending_review",
                  "submitted",
                  "in_progress",
                  "processing",
                  "action_required",
                  "verified",
                  "approved",
                  "rejected"
                ]
              },
              "type": {
                "type": "string",
                "description": "What the verification covers. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "toll_free",
                  "international",
                  "both"
                ]
              },
              "region": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The verification's region. Known values: `us`, `intl`, `both`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "us",
                  "intl",
                  "both"
                ]
              },
              "submittedAt": {
                "type": "string",
                "format": "date-time",
                "description": "When the verification was created. ISO 8601, in UTC."
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time",
                "description": "When the verification last changed. ISO 8601, in UTC."
              }
            },
            "required": [
              "status",
              "type",
              "region",
              "submittedAt",
              "updatedAt"
            ],
            "description": "The business verification. `null` when there is none."
          },
          "apiKey": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The calling key's id. `cli_session_<userId>` for a CLI session."
              },
              "name": {
                "type": "string",
                "description": "`Unknown` for a CLI session."
              },
              "type": {
                "type": "string",
                "enum": [
                  "test",
                  "live"
                ],
                "description": "`test` for a CLI session."
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string",
                  "description": "A permission the calling key or CLI session holds. A CLI session also holds `sms:schedule`, `user:read`, `keys:read` and `keys:write`, or `full` once refreshed from an older session. Known values: `sms:send`, `sms:read`, `verify:send`, `verify:read`, `webhooks:read`, `webhooks:write`, `templates:read`, `templates:write`, `campaigns:read`, `campaigns:write`, `campaigns:send`, `contacts:read`, `contacts:write`, `numbers:read`, `numbers:write`, `tendlc:read`, `tendlc:write`, `rcs:read`, `rcs:write`, `whatsapp:read`, `whatsapp:write`, `short_codes:read`, `short_codes:write`, `links:read`, `links:write`, `calls:read`, `calls:write`, `enterprise:master`, `sms:schedule`, `user:read`, `keys:read`, `keys:write`, `full`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "sms:send",
                    "sms:read",
                    "verify:send",
                    "verify:read",
                    "webhooks:read",
                    "webhooks:write",
                    "templates:read",
                    "templates:write",
                    "campaigns:read",
                    "campaigns:write",
                    "campaigns:send",
                    "contacts:read",
                    "contacts:write",
                    "numbers:read",
                    "numbers:write",
                    "tendlc:read",
                    "tendlc:write",
                    "rcs:read",
                    "rcs:write",
                    "whatsapp:read",
                    "whatsapp:write",
                    "short_codes:read",
                    "short_codes:write",
                    "links:read",
                    "links:write",
                    "calls:read",
                    "calls:write",
                    "enterprise:master",
                    "sms:schedule",
                    "user:read",
                    "keys:read",
                    "keys:write",
                    "full"
                  ]
                }
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "description": "Absent for a CLI session."
              },
              "lastUsedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Absent for a CLI session."
              }
            },
            "required": [
              "id",
              "name",
              "type",
              "scopes"
            ]
          },
          "limits": {
            "type": "object",
            "properties": {
              "messagesPerMinute": {
                "type": "number",
                "enum": [
                  60
                ]
              },
              "messagesPerDay": {
                "anyOf": [
                  {
                    "type": "number",
                    "enum": [
                      100
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      10000
                    ]
                  }
                ],
                "description": "100 for a test key, 10,000 for a live one."
              }
            },
            "required": [
              "messagesPerMinute",
              "messagesPerDay"
            ],
            "description": "Fixed numbers, the same for every account. They are not the limits the API enforces."
          }
        },
        "required": [
          "user",
          "organization",
          "credits",
          "verification",
          "apiKey",
          "limits"
        ]
      },
      "AccountCreditTransaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The transaction's id."
          },
          "amount": {
            "type": "integer",
            "description": "Credits added, or negative for credits spent."
          },
          "type": {
            "type": "string",
            "description": "What kind of transaction it is. Known values: `purchase`, `usage`, `bonus`, `refund`, `transfer`, `admin_grant`, `admin_seed`, `fee`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "purchase",
              "usage",
              "bonus",
              "refund",
              "transfer",
              "admin_grant",
              "admin_seed",
              "fee"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the transaction happened. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "amount",
          "type",
          "description",
          "createdAt"
        ]
      },
      "AccountCredits": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "integer",
            "description": "The credit balance. For a pooled enterprise workspace it is the shared pool's, which can go below zero by up to the overage cap."
          },
          "reservedBalance": {
            "type": "integer",
            "description": "Credits held for messages still being sent."
          },
          "availableBalance": {
            "type": "integer",
            "description": "What can be spent now: `balance` minus `reservedBalance`, plus the overage cap for a pooled workspace, where it is never below 0."
          },
          "billingMode": {
            "type": "string",
            "enum": [
              "prepaid",
              "pooled"
            ],
            "description": "`pooled` when the workspace spends an enterprise credit pool."
          },
          "recentTransactions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountCreditTransaction"
            },
            "description": "The 20 most recent transactions, newest first."
          }
        },
        "required": [
          "balance",
          "reservedBalance",
          "availableBalance",
          "billingMode",
          "recentTransactions"
        ]
      },
      "AccountSuspendedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "account_suspended"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "account_suspended",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "account_suspended"
        ]
      },
      "AddContactsToListRequest": {
        "type": "object",
        "properties": {
          "contact_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "description": "The ids of contacts of this workspace to add. Ids that match none are skipped. A contact already in the list is added again, as a second membership."
          }
        },
        "required": [
          "contact_ids"
        ]
      },
      "AddConversationLabelsRequest": {
        "type": "object",
        "properties": {
          "labelIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "description": "The ids of the labels to add. Labels already on the conversation are kept once."
          }
        },
        "required": [
          "labelIds"
        ]
      },
      "AddMessageLabelsRequest": {
        "type": "object",
        "properties": {
          "labelIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "description": "The labels to add."
          }
        },
        "required": [
          "labelIds"
        ]
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The API key's id."
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "description": "`test` simulates every send and never charges; `live` sends."
          },
          "prefix": {
            "type": "string",
            "description": "The key's first characters followed by `...`, such as `sk_test_v1_a...`. `sk_***...` for a key stored without a prefix."
          },
          "scopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "description": "A permission the key holds. `enterprise:master` belongs to an enterprise master key only, and no key can grant it. `full` is a legacy scope an older key may hold; a rotation keeps it. Known values: `sms:send`, `sms:read`, `verify:send`, `verify:read`, `webhooks:read`, `webhooks:write`, `templates:read`, `templates:write`, `campaigns:read`, `campaigns:write`, `campaigns:send`, `contacts:read`, `contacts:write`, `numbers:read`, `numbers:write`, `tendlc:read`, `tendlc:write`, `rcs:read`, `rcs:write`, `whatsapp:read`, `whatsapp:write`, `short_codes:read`, `short_codes:write`, `links:read`, `links:write`, `calls:read`, `calls:write`, `enterprise:master`, `full`. More can be added at any time, so treat an unknown value as valid.",
              "x-sendly-extensible-enum": [
                "sms:send",
                "sms:read",
                "verify:send",
                "verify:read",
                "webhooks:read",
                "webhooks:write",
                "templates:read",
                "templates:write",
                "campaigns:read",
                "campaigns:write",
                "campaigns:send",
                "contacts:read",
                "contacts:write",
                "numbers:read",
                "numbers:write",
                "tendlc:read",
                "tendlc:write",
                "rcs:read",
                "rcs:write",
                "whatsapp:read",
                "whatsapp:write",
                "short_codes:read",
                "short_codes:write",
                "links:read",
                "links:write",
                "calls:read",
                "calls:write",
                "enterprise:master",
                "full"
              ]
            },
            "description": "The permissions the key holds."
          },
          "permissions": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "description": "A permission the key holds. `enterprise:master` belongs to an enterprise master key only, and no key can grant it. `full` is a legacy scope an older key may hold; a rotation keeps it. Known values: `sms:send`, `sms:read`, `verify:send`, `verify:read`, `webhooks:read`, `webhooks:write`, `templates:read`, `templates:write`, `campaigns:read`, `campaigns:write`, `campaigns:send`, `contacts:read`, `contacts:write`, `numbers:read`, `numbers:write`, `tendlc:read`, `tendlc:write`, `rcs:read`, `rcs:write`, `whatsapp:read`, `whatsapp:write`, `short_codes:read`, `short_codes:write`, `links:read`, `links:write`, `calls:read`, `calls:write`, `enterprise:master`, `full`. More can be added at any time, so treat an unknown value as valid.",
              "x-sendly-extensible-enum": [
                "sms:send",
                "sms:read",
                "verify:send",
                "verify:read",
                "webhooks:read",
                "webhooks:write",
                "templates:read",
                "templates:write",
                "campaigns:read",
                "campaigns:write",
                "campaigns:send",
                "contacts:read",
                "contacts:write",
                "numbers:read",
                "numbers:write",
                "tendlc:read",
                "tendlc:write",
                "rcs:read",
                "rcs:write",
                "whatsapp:read",
                "whatsapp:write",
                "short_codes:read",
                "short_codes:write",
                "links:read",
                "links:write",
                "calls:read",
                "calls:write",
                "enterprise:master",
                "full"
              ]
            },
            "description": "Same as `scopes`."
          },
          "isActive": {
            "type": "boolean",
            "description": "`false` once the key is revoked."
          },
          "isRevoked": {
            "type": "boolean",
            "description": "The opposite of `isActive`. An expired key that was never revoked is still `false`."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was created. ISO 8601, in UTC."
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was last used. ISO 8601, in UTC."
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key stops working: the expiry it was created with, or the end of a rotation's grace period. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "prefix",
          "scopes",
          "permissions",
          "isActive",
          "isRevoked",
          "createdAt",
          "lastUsedAt",
          "expiresAt"
        ],
        "description": "An API key, without its secret, as `GET /api/v1/account/keys` lists it and a rename returns it."
      },
      "ApiKeyDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The API key's id."
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "description": "`test` simulates every send and never charges; `live` sends."
          },
          "prefix": {
            "type": "string",
            "description": "The key's first characters followed by `...`. `sk_***...` for a key stored without a prefix."
          },
          "scopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "description": "A permission the key holds. `enterprise:master` belongs to an enterprise master key only, and no key can grant it. `full` is a legacy scope an older key may hold; a rotation keeps it. Known values: `sms:send`, `sms:read`, `verify:send`, `verify:read`, `webhooks:read`, `webhooks:write`, `templates:read`, `templates:write`, `campaigns:read`, `campaigns:write`, `campaigns:send`, `contacts:read`, `contacts:write`, `numbers:read`, `numbers:write`, `tendlc:read`, `tendlc:write`, `rcs:read`, `rcs:write`, `whatsapp:read`, `whatsapp:write`, `short_codes:read`, `short_codes:write`, `links:read`, `links:write`, `calls:read`, `calls:write`, `enterprise:master`, `full`. More can be added at any time, so treat an unknown value as valid.",
              "x-sendly-extensible-enum": [
                "sms:send",
                "sms:read",
                "verify:send",
                "verify:read",
                "webhooks:read",
                "webhooks:write",
                "templates:read",
                "templates:write",
                "campaigns:read",
                "campaigns:write",
                "campaigns:send",
                "contacts:read",
                "contacts:write",
                "numbers:read",
                "numbers:write",
                "tendlc:read",
                "tendlc:write",
                "rcs:read",
                "rcs:write",
                "whatsapp:read",
                "whatsapp:write",
                "short_codes:read",
                "short_codes:write",
                "links:read",
                "links:write",
                "calls:read",
                "calls:write",
                "enterprise:master",
                "full"
              ]
            },
            "description": "The permissions the key holds."
          },
          "isActive": {
            "type": "boolean",
            "description": "`false` once the key is revoked."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was created. ISO 8601, in UTC."
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was last used. ISO 8601, in UTC."
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key stops working: the expiry it was created with, or the end of a rotation's grace period. ISO 8601, in UTC."
          },
          "revokedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was revoked. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "prefix",
          "scopes",
          "isActive",
          "createdAt",
          "lastUsedAt",
          "expiresAt",
          "revokedAt"
        ],
        "description": "One API key, without its secret."
      },
      "ApiKeyList": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiKey"
            }
          }
        },
        "required": [
          "keys"
        ]
      },
      "ApiKeyRequiredError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "api_key_required"
            ]
          },
          "message": {
            "type": "string"
          },
          "hint": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message",
          "hint"
        ],
        "title": "api_key_required",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "api_key_required"
        ]
      },
      "ApiKeyUsage": {
        "type": "object",
        "properties": {
          "keyId": {
            "type": "string",
            "description": "The key's id, as sent in the path."
          },
          "keyName": {
            "type": "string"
          },
          "summary": {
            "type": "object",
            "properties": {
              "totalRequests": {
                "type": "integer",
                "description": "How many of the key's 100 most recent requests there are: at most 100."
              },
              "totalCredits": {
                "type": "integer",
                "description": "Credits recorded on those requests."
              },
              "lastUsed": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the newest of them was made. ISO 8601, in UTC."
              }
            },
            "required": [
              "totalRequests",
              "totalCredits",
              "lastUsed"
            ]
          },
          "recentRequests": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "endpoint": {
                  "type": "string",
                  "description": "The path that was called, with its query string."
                },
                "method": {
                  "type": "string",
                  "description": "The HTTP method, such as `GET`."
                },
                "statusCode": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "The status the request was answered with. 499 when the client went away first."
                },
                "creditsUsed": {
                  "type": "integer"
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the request was made. ISO 8601, in UTC."
                }
              },
              "required": [
                "endpoint",
                "method",
                "statusCode",
                "creditsUsed",
                "createdAt"
              ]
            },
            "description": "The 20 most recent requests, newest first."
          },
          "endpointBreakdown": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "endpoint": {
                  "type": "string",
                  "description": "The method and path, such as `GET /api/v1/account`."
                },
                "count": {
                  "type": "integer"
                }
              },
              "required": [
                "endpoint",
                "count"
              ]
            },
            "description": "Requests per method and path among the 100 most recent, most called first."
          }
        },
        "required": [
          "keyId",
          "keyName",
          "summary",
          "recentRequests",
          "endpointBreakdown"
        ]
      },
      "ApprovedMessageDraft": {
        "allOf": [
          {
            "$ref": "#/components/schemas/MessageDraft"
          },
          {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "approved"
                ]
              },
              "messageId": {
                "type": "string",
                "description": "The message the approval sent."
              },
              "message": {
                "$ref": "#/components/schemas/SmsSendResult"
              }
            },
            "required": [
              "message"
            ]
          }
        ],
        "description": "The approved draft, with the message the approval sent in `message`, as `POST /api/v1/messages` answered it."
      },
      "AssignTenDlcNumberRequest": {
        "type": "object",
        "properties": {
          "phoneNumber": {
            "type": "string",
            "minLength": 1,
            "description": "A number of this workspace, in E.164 format, exactly as stored. Leading and trailing spaces are trimmed."
          }
        },
        "required": [
          "phoneNumber"
        ]
      },
      "AuthenticationError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "unauthorized",
              "invalid_auth_format",
              "invalid_key_format",
              "invalid_api_key",
              "invalid_cli_token",
              "invalid_token"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "Authentication failed",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "unauthorized",
          "invalid_auth_format",
          "invalid_key_format",
          "invalid_api_key",
          "invalid_cli_token",
          "invalid_token"
        ]
      },
      "AuthenticationFailedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "Authentication failed"
            ]
          },
          "sendlyCode": {
            "type": "string",
            "enum": [
              "authentication_failed"
            ],
            "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
          }
        },
        "required": [
          "error"
        ],
        "description": "`error` holds a sentence, and there is no `message`.",
        "title": "Authentication failed",
        "x-sendly-error-shape": "sentence",
        "x-sendly-error-codes": [],
        "x-sendly-proposed-codes": [
          "authentication_failed"
        ]
      },
      "AuthenticationThrottledError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "too_many_failed_key_attempts",
              "too_many_concurrent_verifications"
            ]
          },
          "message": {
            "type": "string"
          },
          "retryAfter": {
            "type": "integer",
            "description": "Seconds to wait before retrying."
          }
        },
        "required": [
          "error",
          "message",
          "retryAfter"
        ],
        "title": "too_many_failed_key_attempts, too_many_concurrent_verifications",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "too_many_failed_key_attempts",
          "too_many_concurrent_verifications"
        ]
      },
      "AutoLabelRule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The rule's id."
          },
          "userId": {
            "type": "string",
            "description": "The account that created the rule."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace the rule belongs to. `null` for a rule of a key with no workspace."
          },
          "name": {
            "type": "string"
          },
          "conditions": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AutoLabelRuleConditions"
              },
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "object",
                "additionalProperties": {}
              }
            ],
            "description": "The conditions, as stored. Create and update check them now, so a rule written since 6 Oct 2026 holds the object described. A rule written before then holds what it was sent, which the server did not check, so it can also be a string, a number, a boolean, an array, or an object whose fields have other types."
          },
          "actions": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AutoLabelRuleActions"
              },
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "object",
                "additionalProperties": {}
              }
            ],
            "description": "The actions, as stored. Create and update check them now, so a rule written since 6 Oct 2026 holds the object described. A rule written before then holds what it was sent, which the server did not check, so it can also be a string, a number, a boolean, an array, or an object whose fields have other types."
          },
          "enabled": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the rule runs. `true` for a new rule. Only `true` runs. `null` only on a rule an older `PATCH` with `enabled: null` changed: `PATCH` refuses `null` now."
          },
          "priority": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Rules run lowest first, and every matching rule runs. `0` unless set. `null` only on a rule an older `PATCH` with `priority: null` changed: a `null` now leaves it as it is."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the rule was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the rule was last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "name",
          "conditions",
          "actions",
          "enabled",
          "priority",
          "createdAt",
          "updatedAt"
        ],
        "description": "A rule that labels or closes a conversation when an inbound message's classification matches it."
      },
      "AutoLabelRuleActions": {
        "type": "object",
        "properties": {
          "addLabels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "closeConversation": {
            "type": "boolean"
          }
        },
        "description": "The actions. A rule written since 6 Oct 2026 holds only these fields, with `addLabels` always set; an older rule holds whatever it was sent."
      },
      "AutoLabelRuleConditions": {
        "type": "object",
        "properties": {
          "intent": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The intent, or intents, the rule matches."
          },
          "sentiment": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The sentiment, or sentiments, the rule matches."
          },
          "intentConfidenceMin": {
            "type": "number"
          },
          "sentimentConfidenceMin": {
            "type": "number"
          }
        },
        "description": "The conditions. A rule written since 6 Oct 2026 holds only these fields; an older rule holds whatever it was sent."
      },
      "AutoLabelRuleList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AutoLabelRule"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "AvailableNumber": {
        "type": "object",
        "properties": {
          "phoneNumber": {
            "type": "string",
            "description": "The number, in E.164 format."
          },
          "country": {
            "type": "string",
            "description": "The country searched, as an upper-case ISO 3166-1 alpha-2 code."
          },
          "numberType": {
            "type": "string",
            "description": "The number's type: the carrier's own, or the `type` searched for."
          },
          "monthlyCost": {
            "type": "string",
            "description": "The monthly price, in `currency`, as a decimal string with two places, such as `\"6.75\"`. Never below the standard floor."
          },
          "currency": {
            "type": "string",
            "description": "The ISO 4217 currency code, such as `USD`."
          }
        },
        "required": [
          "phoneNumber",
          "country",
          "numberType",
          "monthlyCost",
          "currency"
        ]
      },
      "AvailableNumberList": {
        "type": "object",
        "properties": {
          "numbers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AvailableNumber"
            }
          }
        },
        "required": [
          "numbers"
        ]
      },
      "BackfillWebhookRequest": {
        "type": "object",
        "properties": {
          "since": {
            "type": "string",
            "description": "The window's start. Defaults to 24 hours ago."
          },
          "until": {
            "type": "string",
            "description": "The window's end. Defaults to now."
          },
          "event_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.sent",
                "message.delivered",
                "message.failed"
              ]
            },
            "description": "The events to rebuild. Defaults to the webhook's events. Only `message.sent`, `message.delivered` and `message.failed` the webhook subscribes to are used."
          },
          "eventTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.sent",
                "message.delivered",
                "message.failed"
              ]
            },
            "description": "Takes precedence over `event_types`."
          },
          "limit": {
            "type": "integer",
            "description": "At most this many events, 1 to 10,000. Defaults to 1,000."
          }
        },
        "description": "Every field is optional. There is no dry run: `dry_run` is ignored."
      },
      "BareInternalError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "internal_error"
            ]
          }
        },
        "required": [
          "error"
        ],
        "description": "Only `error`, with no `message`.",
        "title": "internal_error, with no message",
        "x-sendly-error-shape": "bare",
        "x-sendly-error-codes": [
          "internal_error"
        ]
      },
      "BareNotFoundError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "not_found"
            ]
          }
        },
        "required": [
          "error"
        ],
        "description": "Only `error`, with no `message`.",
        "title": "not_found, with no message",
        "x-sendly-error-shape": "bare",
        "x-sendly-error-codes": [
          "not_found"
        ]
      },
      "BestPrefill": {
        "type": "object",
        "properties": {
          "prefill": {
            "$ref": "#/components/schemas/BestPrefillValues"
          },
          "sourceWorkspaceCount": {
            "type": "integer",
            "description": "How many active, verified business verifications were merged. It counts verifications, not distinct workspaces."
          }
        },
        "required": [
          "prefill",
          "sourceWorkspaceCount"
        ]
      },
      "BestPrefillValues": {
        "type": "object",
        "properties": {
          "monthlyVolume": {
            "type": "string",
            "description": "The expected monthly message volume, such as `1,000`."
          },
          "useCase": {
            "type": "string",
            "description": "The use case, such as `Appointments`."
          },
          "useCaseSummary": {
            "type": "string",
            "description": "What the messages are for, in the customer's words."
          },
          "sampleMessages": {
            "type": "string",
            "description": "Example messages."
          },
          "optInWorkflow": {
            "type": "string",
            "description": "How recipients opt in."
          },
          "optInImageUrls": {
            "type": "string",
            "description": "Opt-in proof image URLs, joined by commas."
          },
          "optInSource": {
            "type": "string",
            "description": "Where the opt-in proof comes from: a Sendly-hosted opt-in page, an uploaded screenshot, or both. Known values: `hosted`, `manual`, `mixed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "hosted",
              "manual",
              "mixed"
            ]
          },
          "privacyUrl": {
            "type": "string",
            "description": "The privacy policy URL."
          },
          "termsUrl": {
            "type": "string",
            "description": "The terms and conditions URL."
          },
          "additionalInformation": {
            "type": "string",
            "description": "Anything else the reviewer should know."
          },
          "isvReseller": {
            "type": "string",
            "description": "The reseller the messages go through."
          },
          "ageGatedContent": {
            "type": "boolean",
            "description": "Whether the messages carry 18+ content."
          }
        },
        "description": "Each field is the most recently updated non-empty value among the caller's verified business verifications, and absent when none has one."
      },
      "BulkMarkValidResult": {
        "type": "object",
        "properties": {
          "cleared": {
            "type": "integer",
            "description": "How many contacts were updated: every one of the workspace's contacts named, whether or not it was flagged."
          }
        },
        "required": [
          "cleared"
        ]
      },
      "BuyNumberDocumentsRequired": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "documents_required"
            ]
          },
          "message": {
            "type": "string"
          },
          "requirements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NumberOrderingRequirement"
            }
          },
          "action": {
            "$ref": "#/components/schemas/NumberBuyAction"
          }
        },
        "required": [
          "status",
          "message",
          "requirements",
          "action"
        ],
        "description": "The country needs business details and documents first. The hosted step lasts 7 days; once it is done, call buy again with its `actionCode`.",
        "title": "Documents required"
      },
      "BuyNumberPaymentRequired": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "payment_required"
            ]
          },
          "message": {
            "type": "string"
          },
          "action": {
            "$ref": "#/components/schemas/NumberBuyAction"
          }
        },
        "required": [
          "status",
          "message",
          "action"
        ],
        "description": "The workspace has no payment method, or it could not be checked. Once one is added on the hosted page, call buy again.",
        "title": "Payment method required"
      },
      "BuyNumberProvisioning": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "provisioning"
            ]
          },
          "number": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The number's id."
              },
              "phoneNumber": {
                "type": "string",
                "description": "The number, in E.164 format."
              },
              "status": {
                "type": "string",
                "enum": [
                  "provisioning"
                ]
              }
            },
            "required": [
              "id",
              "phoneNumber",
              "status"
            ]
          }
        },
        "required": [
          "status",
          "number"
        ],
        "description": "The order was placed. Poll `GET /api/v1/numbers/{id}` until it is `active`.",
        "title": "Provisioning"
      },
      "BuyNumberRequest": {
        "type": "object",
        "properties": {
          "phoneNumber": {
            "type": "string",
            "description": "The number to buy, in E.164 format, from `GET /api/v1/numbers/available`."
          },
          "countryCode": {
            "type": "string",
            "description": "The number's ISO 3166-1 alpha-2 country code, in any case."
          },
          "phoneNumberType": {
            "type": "string",
            "description": "The number's type, as the search returned it. Must be `local` for Canada."
          },
          "monthlyCost": {
            "type": "string",
            "description": "The price the search showed. Kept with a hosted step for display only: the price charged is worked out again."
          },
          "actionCode": {
            "type": "string",
            "description": "The `actionCode` of a completed `documents_required` step, to finish the purchase. Not the display `code`."
          },
          "campaignId": {
            "type": "string",
            "description": "US local numbers only: the active 10DLC campaign to assign the number to."
          },
          "allowUnregistered": {
            "type": "boolean",
            "description": "US local numbers only. Defaults to `true`: with no single active campaign to assign it to, the number is bought unregistered and cannot send until it is assigned. `false` refuses the purchase instead."
          }
        },
        "required": [
          "phoneNumber"
        ]
      },
      "BuyNumberUnderReview": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "under_review"
            ]
          },
          "number": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The number's id."
              },
              "phoneNumber": {
                "type": "string",
                "description": "The number, in E.164 format."
              },
              "status": {
                "type": "string",
                "enum": [
                  "requirements_required"
                ]
              }
            },
            "required": [
              "id",
              "phoneNumber",
              "status"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "status",
          "number",
          "message"
        ],
        "description": "The documents are in and the order was placed. The number cannot send until it is reviewed and `active`.",
        "title": "Under review"
      },
      "BuyUsLocalNumberProvisioning": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "provisioning"
            ]
          },
          "number": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The number's id."
              },
              "phoneNumber": {
                "type": "string",
                "description": "The number, in E.164 format."
              },
              "status": {
                "type": "string",
                "description": "`provisioning` for a new order. When the workspace already owns the number, its current status, which can be `released` for a number it released whose record is kept. Known values: `provisioning`, `active`, `requirements_required`, `failed`, `suspended`, `released`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "provisioning",
                  "active",
                  "requirements_required",
                  "failed",
                  "suspended",
                  "released"
                ]
              }
            },
            "required": [
              "id",
              "phoneNumber",
              "status"
            ]
          },
          "registrationRequired": {
            "type": "boolean",
            "description": "`true` when the number was bought without a 10DLC campaign, so it cannot send until it is assigned to one."
          }
        },
        "required": [
          "status",
          "number",
          "registrationRequired"
        ],
        "description": "A US local number was ordered, or the workspace already owns it and this is its record.",
        "title": "US local number provisioning"
      },
      "Call": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The call's id."
          },
          "object": {
            "type": "string",
            "enum": [
              "call"
            ]
          },
          "kind": {
            "type": "string",
            "description": "`pstn` for a phone call, `internal` for a browser call between teammates. Known values: `pstn`, `internal`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "pstn",
              "internal"
            ]
          },
          "channel": {
            "type": "string",
            "description": "How the far end reached the call: the phone network, WhatsApp, or a browser. Every `internal` call is `browser`. Known values: `phone`, `whatsapp`, `browser`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "phone",
              "whatsapp",
              "browser"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "status": {
            "type": "string",
            "description": "Where the call is in its lifecycle. `ringing` and `active` are live; `completed`, `no_answer`, `busy`, `cancelled`, `declined` and `failed` are final. Known values: `ringing`, `active`, `suspended`, `completed`, `no_answer`, `busy`, `cancelled`, `declined`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "ringing",
              "active",
              "suspended",
              "completed",
              "no_answer",
              "busy",
              "cancelled",
              "declined",
              "failed"
            ]
          },
          "handledBy": {
            "type": "string",
            "description": "Who answers: one of the workspace's AI agents, or the team in the dashboard. Known values: `agent`, `dashboard`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "agent",
              "dashboard"
            ]
          },
          "agentId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The AI agent on the call, or `null` when none was."
          },
          "from": {
            "type": [
              "string",
              "null"
            ],
            "description": "The calling number in E.164 format, or `null` for an internal call."
          },
          "to": {
            "type": [
              "string",
              "null"
            ],
            "description": "The called number in E.164 format, or `null` for an internal call."
          },
          "callerName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The calling side's display name, or `null` when none was stored: the agent's name on a call an agent placed, the teammate's name on a call placed from the dashboard or a browser, and the calling number, or `Unknown caller`, on an inbound phone call."
          },
          "calleeName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The called side's display name, or `null` when none was stored: the dialled number on an outbound phone call, the agent's name when an agent answers, the dialled number on an inbound phone call the team answers, and the teammate's name on a browser call."
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the call started ringing. ISO 8601, in UTC."
          },
          "answeredAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the call was answered. ISO 8601, in UTC."
          },
          "endedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the call ended. `null` while it is live. ISO 8601, in UTC."
          },
          "durationSecs": {
            "type": "integer",
            "description": "Seconds from answer to end. 0 until an answered call ends."
          },
          "creditsCharged": {
            "type": "integer",
            "description": "Credits charged so far. A phone call is charged per started minute while it runs, and the figure is final once `billing` is `settled`."
          },
          "billing": {
            "type": "string",
            "enum": [
              "metered",
              "settled",
              "unbilled"
            ],
            "description": "`metered` while a phone call is live and still being charged, `settled` once it has ended, `unbilled` for an internal call, one from before calls were charged, or one started while charging is switched off for the platform."
          },
          "hangupClass": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` while the call is live.",
            "x-sendly-extensible-enum": [
              "normal",
              "caller_hung_up",
              "caller_cancelled",
              "caller_left",
              "callee_declined",
              "ring_timeout",
              "room_closed",
              "setup_failed",
              "media_aborted",
              "max_duration",
              "agent_dispatch_failed",
              "peer_connection_lost",
              "peer_left",
              "room_closed_unanswered",
              "agent_left",
              "agent_left_unanswered",
              "agent_agent_hangup",
              "agent_caller_left",
              "agent_caller_never_joined",
              "agent_already_ended",
              "agent_api_unreachable",
              "agent_ended",
              "callee_hung_up",
              "callee_busy",
              "invalid_number",
              "destination_rejected",
              "credits_exhausted",
              "ended",
              "transferred",
              "voicemail",
              "voicemail_unavailable"
            ]
          },
          "recordingStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "The recording's state, or `null` when nothing was recorded. Known values: `recording`, `ready`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "recording",
              "ready",
              "failed"
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "The string map sent as `metadata` when the call was placed over the API. `{}` when none was."
          }
        },
        "required": [
          "id",
          "object",
          "kind",
          "channel",
          "direction",
          "status",
          "handledBy",
          "agentId",
          "from",
          "to",
          "callerName",
          "calleeName",
          "startedAt",
          "answeredAt",
          "endedAt",
          "durationSecs",
          "creditsCharged",
          "billing",
          "hangupClass",
          "recordingStatus",
          "metadata"
        ],
        "description": "A call, as the `/api/v1/calls` operations return it."
      },
      "CallList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Call"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/OffsetHasMorePagination"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "CallRecording": {
        "type": "object",
        "properties": {
          "callId": {
            "type": "string",
            "description": "The call the recording belongs to."
          },
          "status": {
            "type": "string",
            "description": "`none` when nothing was recorded, `recording` while it is still being written, `ready` when `url` can be fetched, `failed` when it could not be produced, including a recording marked ready that has no stored file. Known values: `none`, `recording`, `ready`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "none",
              "recording",
              "ready",
              "failed"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "A signed download link, valid for five minutes. Set only when `ready`."
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When `url` stops working. Set only when `ready`. ISO 8601, in UTC."
          },
          "contentType": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "audio/ogg",
              null
            ],
            "description": "`audio/ogg` when `ready`, otherwise `null`. An agent call is recorded in stereo: the agent on the left channel, the other party on the right."
          }
        },
        "required": [
          "callId",
          "status",
          "url",
          "expiresAt",
          "contentType"
        ]
      },
      "CallTranscriptLine": {
        "type": "object",
        "properties": {
          "speaker": {
            "type": "string",
            "enum": [
              "caller",
              "agent"
            ]
          },
          "text": {
            "type": "string",
            "description": "What was said."
          },
          "atMs": {
            "type": "integer",
            "description": "Milliseconds from the start of the call."
          }
        },
        "required": [
          "speaker",
          "text",
          "atMs"
        ]
      },
      "CallWithTranscript": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Call"
          },
          {
            "type": "object",
            "properties": {
              "transcript": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CallTranscriptLine"
                },
                "description": "The agent call's transcript, oldest line first: an empty array when nothing was said. Present only when `handledBy` is `agent`."
              }
            }
          }
        ],
        "description": "A call, with the transcript when an AI agent handled it."
      },
      "Campaign": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The campaign's id, such as `camp_...`."
          },
          "userId": {
            "type": "string",
            "description": "The user who created the campaign."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` for a personal campaign outside any workspace."
          },
          "name": {
            "type": "string",
            "description": "The campaign's name."
          },
          "status": {
            "type": "string",
            "description": "Where the campaign is. A sent campaign is `completed`, also when it had no recipients. Known values: `draft`, `scheduled`, `sending`, `completed`, `cancelled`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "scheduled",
              "sending",
              "completed",
              "cancelled",
              "failed"
            ]
          },
          "messageText": {
            "type": "string",
            "description": "The message. `{{name}}` and `{{brand_name}}` (or `{name}` and `{brand_name}`) are filled in per recipient."
          },
          "fromSender": {
            "type": [
              "string",
              "null"
            ],
            "description": "The number a scheduled send goes from, when one was set."
          },
          "targetType": {
            "type": "string",
            "description": "Who the campaign goes to: one contact list, every contact of the workspace, or the numbers in `manualRecipients`. Known values: `contact_list`, `all_contacts`, `manual`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "contact_list",
              "all_contacts",
              "manual"
            ]
          },
          "targetListId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact list the campaign targets."
          },
          "manualRecipients": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "phone": {
                  "type": "string",
                  "description": "The recipient's phone number."
                },
                "name": {
                  "type": "string",
                  "description": "The name `{{name}}` is filled with for this recipient."
                }
              },
              "required": [
                "phone"
              ],
              "description": "A recipient of a `manual` campaign, stored as sent."
            },
            "description": "The recipients of a `manual` campaign."
          },
          "excludeOptedOut": {
            "type": "boolean",
            "description": "Stored as sent. Opted-out contacts are left out of every send whatever this says."
          },
          "sendNow": {
            "type": "boolean",
            "description": "Stored as sent. Nothing reads it."
          },
          "scheduledAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the campaign is scheduled to send. ISO 8601, in UTC."
          },
          "timezone": {
            "type": "string",
            "description": "The timezone stored with the schedule. Defaults to `America/New_York`."
          },
          "batchId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The message batch the send created."
          },
          "totalRecipients": {
            "type": "integer",
            "description": "How many recipients the campaign has: the estimate stored at scheduling, then the batch's size once sent."
          },
          "estimatedCredits": {
            "type": "integer",
            "description": "The credits the campaign was estimated to cost when it was scheduled. Once sent, the credits the batch had used when the send answered, which is 0 for a batch sent in the background."
          },
          "sentCount": {
            "type": "integer",
            "description": "How many messages the send created."
          },
          "deliveredCount": {
            "type": "integer",
            "description": "How many of them were delivered."
          },
          "failedCount": {
            "type": "integer",
            "description": "How many of them failed, bounced or were undelivered."
          },
          "creditsUsed": {
            "type": "integer",
            "description": "The credits the send used."
          },
          "creditsRefunded": {
            "type": "integer",
            "description": "Always 0: a send does not record its refunds on the campaign."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the campaign was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the campaign last changed. ISO 8601, in UTC."
          },
          "sentAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When sending started. ISO 8601, in UTC."
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When sending finished. ISO 8601, in UTC."
          },
          "text": {
            "type": "string",
            "description": "The same as `messageText`."
          },
          "contact_list_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "`targetListId` as a list: one id, or empty when there is none."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "The same as `createdAt`. ISO 8601, in UTC."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "The same as `updatedAt`. ISO 8601, in UTC."
          },
          "targetList": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The contact list's id."
              },
              "userId": {
                "type": "string",
                "description": "The user who created the list."
              },
              "organizationId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The workspace the list belongs to."
              },
              "name": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "contactCount": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "How many contacts the list holds."
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "description": "When the list was created. ISO 8601, in UTC."
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time",
                "description": "When the list last changed. ISO 8601, in UTC."
              }
            },
            "required": [
              "id",
              "userId",
              "organizationId",
              "name",
              "description",
              "contactCount",
              "createdAt",
              "updatedAt"
            ],
            "description": "The contact list the campaign targets, as it is stored, when it still exists in the workspace. Only `GET /api/v1/campaigns` and `GET /api/v1/campaigns/{id}` send it."
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "name",
          "status",
          "messageText",
          "fromSender",
          "targetType",
          "targetListId",
          "manualRecipients",
          "excludeOptedOut",
          "sendNow",
          "scheduledAt",
          "timezone",
          "batchId",
          "totalRecipients",
          "estimatedCredits",
          "sentCount",
          "deliveredCount",
          "failedCount",
          "creditsUsed",
          "creditsRefunded",
          "createdAt",
          "updatedAt",
          "sentAt",
          "completedAt",
          "text",
          "contact_list_ids",
          "created_at",
          "updated_at"
        ],
        "description": "A bulk SMS campaign."
      },
      "CampaignList": {
        "type": "object",
        "properties": {
          "campaigns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Campaign"
            }
          },
          "total": {
            "type": "integer",
            "description": "How many items match, across every page."
          },
          "limit": {
            "type": "integer",
            "description": "The page size used."
          },
          "offset": {
            "type": "integer",
            "description": "How many items were skipped."
          }
        },
        "required": [
          "campaigns",
          "total",
          "limit",
          "offset"
        ]
      },
      "CampaignPreview": {
        "type": "object",
        "properties": {
          "totalRecipients": {
            "type": "integer",
            "description": "Recipients who are neither opted out nor flagged as unable to receive texts."
          },
          "estimatedCredits": {
            "type": "integer",
            "description": "The credits sending to the reachable recipients would cost."
          },
          "optedOutCount": {
            "type": "integer",
            "description": "Contacts left out because they opted out."
          },
          "invalidCount": {
            "type": "integer",
            "description": "Contacts whose phone number is missing or shorter than 10 characters."
          },
          "invalidNumberCount": {
            "type": "integer",
            "description": "Contacts left out because they are flagged as unable to receive texts."
          },
          "landlineCount": {
            "type": "integer",
            "description": "Of those, the ones flagged as landlines."
          },
          "sampleRecipients": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "phone": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              },
              "required": [
                "phone"
              ]
            },
            "description": "Up to five of the recipients."
          },
          "blockedCount": {
            "type": "integer",
            "description": "Recipients the account's verification cannot reach."
          },
          "sendableCount": {
            "type": "integer",
            "description": "`totalRecipients` less `blockedCount`."
          },
          "byCountry": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "count": {
                  "type": "integer"
                },
                "credits": {
                  "type": "integer"
                },
                "allowed": {
                  "type": "boolean"
                },
                "blockedReason": {
                  "type": "string"
                }
              },
              "required": [
                "count",
                "credits",
                "allowed"
              ]
            },
            "description": "Recipients per destination country code, or `unknown`, with their cost."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What would stop or limit the send."
          },
          "messagingProfile": {
            "type": "object",
            "properties": {
              "canSendDomestic": {
                "type": "boolean"
              },
              "canSendInternational": {
                "type": "boolean"
              },
              "verificationType": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "verificationStatus": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "canSendDomestic",
              "canSendInternational",
              "verificationType",
              "verificationStatus"
            ]
          },
          "recipientCount": {
            "type": "integer",
            "description": "The same as `totalRecipients`."
          },
          "currentBalance": {
            "type": "integer",
            "description": "The account's credit balance."
          },
          "hasEnoughCredits": {
            "type": "boolean",
            "description": "Whether the balance covers `estimatedCredits`. Always `true` for a test key."
          }
        },
        "required": [
          "totalRecipients",
          "estimatedCredits",
          "optedOutCount",
          "invalidCount",
          "invalidNumberCount",
          "landlineCount",
          "sampleRecipients",
          "blockedCount",
          "sendableCount",
          "byCountry",
          "warnings",
          "messagingProfile",
          "recipientCount",
          "currentBalance",
          "hasEnoughCredits"
        ]
      },
      "CampaignSendQueued": {
        "type": "object",
        "properties": {
          "batchId": {
            "type": "string",
            "description": "The message batch the send created."
          },
          "status": {
            "type": "string",
            "enum": [
              "processing"
            ]
          },
          "total": {
            "type": "integer",
            "description": "How many messages will be sent."
          },
          "sent": {
            "type": "number",
            "enum": [
              0
            ]
          },
          "failed": {
            "type": "number",
            "enum": [
              0
            ]
          },
          "optedOutSkipped": {
            "type": "integer",
            "description": "Recipients left out because they opted out."
          },
          "invalidSkipped": {
            "type": "integer",
            "description": "Recipients left out because they cannot receive texts."
          },
          "creditsUsed": {
            "type": "number",
            "enum": [
              0
            ]
          },
          "creditsRefunded": {
            "type": "number",
            "enum": [
              0
            ]
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "The recipient's position in the batch."
                },
                "id": {
                  "type": "string",
                  "description": "The message's id. Empty when the message could not be recorded."
                },
                "to": {
                  "type": "string",
                  "description": "The recipient, in E.164 format."
                },
                "status": {
                  "type": "string",
                  "description": "What happened to the message. Known values: `sent`, `failed`, `retrying`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "sent",
                    "failed",
                    "retrying"
                  ]
                },
                "error": {
                  "type": "string",
                  "description": "Why the message failed."
                }
              },
              "required": [
                "index",
                "id",
                "to",
                "status"
              ]
            },
            "maxItems": 0
          }
        },
        "required": [
          "batchId",
          "status",
          "total",
          "sent",
          "failed",
          "optedOutSkipped",
          "invalidSkipped",
          "creditsUsed",
          "creditsRefunded",
          "messages"
        ],
        "description": "The batch was queued and is sent in the background. Its messages are listed by `GET /api/v1/messages/batch/{id}`, with the `batchId` as the id.",
        "title": "Campaign queued"
      },
      "CampaignSendResult": {
        "type": "object",
        "properties": {
          "batchId": {
            "type": "string",
            "description": "The message batch the send created."
          },
          "status": {
            "type": "string",
            "description": "How the batch finished. Known values: `completed`, `partial_failure`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "completed",
              "partial_failure",
              "failed"
            ]
          },
          "total": {
            "type": "integer",
            "description": "How many recipients the campaign had."
          },
          "sent": {
            "type": "integer"
          },
          "failed": {
            "type": "integer"
          },
          "retrying": {
            "type": "integer",
            "description": "Messages whose send is being retried."
          },
          "optedOutSkipped": {
            "type": "integer",
            "description": "Recipients left out because they opted out."
          },
          "invalidSkipped": {
            "type": "integer",
            "description": "Recipients left out because they cannot receive texts."
          },
          "creditsUsed": {
            "type": "integer"
          },
          "creditsRefunded": {
            "type": "integer"
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "The recipient's position in the batch."
                },
                "id": {
                  "type": "string",
                  "description": "The message's id. Empty when the message could not be recorded."
                },
                "to": {
                  "type": "string",
                  "description": "The recipient, in E.164 format."
                },
                "status": {
                  "type": "string",
                  "description": "What happened to the message. Known values: `sent`, `failed`, `retrying`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "sent",
                    "failed",
                    "retrying"
                  ]
                },
                "error": {
                  "type": "string",
                  "description": "Why the message failed."
                }
              },
              "required": [
                "index",
                "id",
                "to",
                "status"
              ]
            }
          }
        },
        "required": [
          "batchId",
          "status",
          "total",
          "sent",
          "failed",
          "retrying",
          "optedOutSkipped",
          "invalidSkipped",
          "creditsUsed",
          "creditsRefunded",
          "messages"
        ],
        "description": "Every message was sent, or simulated, before the answer.",
        "title": "Campaign sent"
      },
      "CancelledPort": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The port request's id."
          },
          "status": {
            "type": "string",
            "enum": [
              "cancelled"
            ]
          }
        },
        "required": [
          "id",
          "status"
        ]
      },
      "CancelledScheduledMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The scheduled message's id."
          },
          "status": {
            "type": "string",
            "enum": [
              "cancelled"
            ]
          },
          "creditsRefunded": {
            "type": "integer",
            "description": "The credits given back: all it reserved."
          }
        },
        "required": [
          "id",
          "status",
          "creditsRefunded"
        ]
      },
      "CheckPortabilityRequest": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "phoneNumbers": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "minItems": 1,
                "description": "The numbers to check, in E.164 format."
              }
            },
            "required": [
              "phoneNumbers"
            ]
          },
          {
            "type": "object",
            "properties": {
              "phoneNumber": {
                "type": "string",
                "minLength": 1,
                "description": "One number to check. Read only when `phoneNumbers` is not an array."
              }
            },
            "required": [
              "phoneNumber"
            ]
          }
        ],
        "description": "`phoneNumbers` or `phoneNumber`. The numbers are passed on as sent. An empty `phoneNumbers` array wins over `phoneNumber` and is refused."
      },
      "CheckVerificationRequest": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "minLength": 1,
            "description": "The code the user entered."
          }
        },
        "required": [
          "code"
        ]
      },
      "CheckVerificationResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The verification's id."
          },
          "status": {
            "type": "string",
            "enum": [
              "verified"
            ]
          },
          "phone": {
            "type": "string",
            "description": "The phone number the code went to."
          },
          "verified_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the right code was first checked. ISO 8601, in UTC. Absent only for an already verified verification with no time recorded."
          }
        },
        "required": [
          "id",
          "status",
          "phone"
        ]
      },
      "CliSessionInvalidError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "unauthorized"
            ]
          },
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "invalid_token"
            ]
          },
          "hint": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message",
          "code",
          "hint"
        ],
        "title": "unauthorized: CLI session invalid",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "unauthorized"
        ]
      },
      "CliSessionUserGoneError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_token"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "invalid_token",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "invalid_token"
        ]
      },
      "CloneCampaignRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "The copy's name. Without one, or with a blank one, it is the original's name followed by ` (Copy)`."
          }
        }
      },
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The contact's id."
          },
          "phone_number": {
            "type": "string",
            "description": "The contact's phone number, in E.164 format."
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "Your own JSON object, as sent. `{}` when none was sent; `null` after a `PATCH` that sent `metadata: null`."
          },
          "opted_out": {
            "type": "boolean",
            "description": "Whether the contact opted out. Sends to an opted-out contact are refused."
          },
          "line_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "The line type a carrier lookup reported, such as `mobile` or `fixed line`."
          },
          "carrier_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The carrier a carrier lookup reported."
          },
          "line_type_checked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the number was last looked up. ISO 8601, in UTC."
          },
          "invalid_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why Sendly flagged the number as unable to receive texts. Campaigns skip a flagged contact. Known values: `landline`, `invalid_number`, `non_sms_capable`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "landline",
              "invalid_number",
              "non_sms_capable"
            ]
          },
          "invalidated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the number was flagged. ISO 8601, in UTC."
          },
          "user_marked_valid_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When someone marked the contact valid. While set, a failed send or a lookup never flags it again. ISO 8601, in UTC."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the contact was created. ISO 8601, in UTC."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the contact last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "phone_number",
          "name",
          "email",
          "metadata",
          "opted_out",
          "line_type",
          "carrier_name",
          "line_type_checked_at",
          "invalid_reason",
          "invalidated_at",
          "user_marked_valid_at",
          "created_at",
          "updated_at"
        ],
        "description": "A contact, as `GET /api/v1/contacts` returns it."
      },
      "ContactCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The contact's id."
          },
          "phone_number": {
            "type": "string",
            "description": "The contact's phone number, in E.164 format."
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object, as sent. `{}` when none was sent."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the contact was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "phone_number",
          "name",
          "email",
          "metadata",
          "created_at"
        ],
        "description": "The contact `POST /api/v1/contacts` created. It has fewer fields than `Contact`."
      },
      "ContactList": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The list's id."
          },
          "name": {
            "type": "string",
            "description": "The list's name, trimmed."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "The list's description. `null` when it has none."
          },
          "contact_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How many memberships the list had when contacts were last added to it or removed from it. A contact added twice counts twice, and deleting a contact does not lower it. The column allows `null`, though every list is created with 0."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the list was created. ISO 8601, in UTC."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the list was last changed, including when its members changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "contact_count",
          "created_at",
          "updated_at"
        ],
        "description": "A contact list, as `GET /api/v1/contact-lists`, `PATCH /api/v1/contact-lists/{id}` and `GET /api/v1/contact-lists/{id}` return it."
      },
      "ContactListCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The list's id."
          },
          "name": {
            "type": "string",
            "description": "The list's name, trimmed."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "The list's description. `null` when it has none."
          },
          "contact_count": {
            "type": "number",
            "enum": [
              0
            ],
            "description": "Always 0: a new list has no members."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the list was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "contact_count",
          "created_at"
        ],
        "description": "The list just created. Unlike the other contact list responses, it has no `updated_at`."
      },
      "ContactListDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ContactList"
          },
          {
            "type": "object",
            "properties": {
              "contacts": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ContactListMember"
                },
                "description": "One page of the list's members. The page is chosen newest added first, but the contacts in it come back in no set order. A contact added more than once appears once, so a page can hold fewer contacts than `limit` even when more follow."
              },
              "contacts_total": {
                "type": "integer",
                "description": "How many memberships the list has, across every page. A contact added twice counts twice."
              }
            },
            "required": [
              "contacts",
              "contacts_total"
            ]
          }
        ],
        "description": "A contact list with one page of its members."
      },
      "ContactListMember": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The contact's id."
          },
          "phone_number": {
            "type": "string",
            "description": "The contact's phone number, in E.164 format."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact's name."
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact's email address."
          }
        },
        "required": [
          "id",
          "phone_number",
          "name",
          "email"
        ],
        "description": "A contact in a list, in short form."
      },
      "ContactListResponse": {
        "type": "object",
        "properties": {
          "contacts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Contact"
            }
          },
          "total": {
            "type": "integer",
            "description": "How many items match, across every page."
          },
          "limit": {
            "type": "integer",
            "description": "The page size used."
          },
          "offset": {
            "type": "integer",
            "description": "How many items were skipped."
          }
        },
        "required": [
          "contacts",
          "total",
          "limit",
          "offset"
        ]
      },
      "ContactLists": {
        "type": "object",
        "properties": {
          "lists": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactList"
            }
          }
        },
        "required": [
          "lists"
        ]
      },
      "ContactLookupResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "alreadyRunning": {
            "type": "boolean",
            "description": "`true` when a lookup for the same scope is still running, so none was started."
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "alreadyRunning",
          "message"
        ]
      },
      "ContactOptOutResult": {
        "type": "object",
        "properties": {
          "phone_number": {
            "type": "string",
            "description": "The number, as stored."
          },
          "opted_out": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The opted-out contact. `null` when creating it failed, in which case nothing was stored."
          }
        },
        "required": [
          "phone_number",
          "opted_out",
          "contact_id"
        ]
      },
      "ContactRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The contact's id."
          },
          "userId": {
            "type": "string",
            "description": "The id of the user who owns the contact."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact's workspace."
          },
          "phoneNumber": {
            "type": "string",
            "description": "The contact's phone number, in E.164 format."
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "Your own JSON object, as sent. `{}` when none was sent; `null` after a `PATCH` that sent `metadata: null`."
          },
          "optedOut": {
            "type": "boolean"
          },
          "optedOutAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the contact opted out. ISO 8601, in UTC."
          },
          "optedOutKeyword": {
            "type": [
              "string",
              "null"
            ],
            "description": "How the contact opted out: the keyword they texted, such as `STOP`, or `API`."
          },
          "optedInAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the contact opted in. ISO 8601, in UTC."
          },
          "optedInMethod": {
            "type": [
              "string",
              "null"
            ],
            "description": "How the contact opted in, such as `csv_import`."
          },
          "optedInSource": {
            "type": [
              "string",
              "null"
            ]
          },
          "lineType": {
            "type": [
              "string",
              "null"
            ],
            "description": "The line type a carrier lookup reported, such as `mobile` or `fixed line`."
          },
          "carrierName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The carrier a carrier lookup reported."
          },
          "lineTypeCheckedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the number was last looked up. ISO 8601, in UTC."
          },
          "invalidReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why Sendly flagged the number as unable to receive texts. Campaigns skip a flagged contact. Known values: `landline`, `invalid_number`, `non_sms_capable`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "landline",
              "invalid_number",
              "non_sms_capable"
            ]
          },
          "invalidatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the number was flagged. ISO 8601, in UTC."
          },
          "userMarkedValidAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When someone marked the contact valid. While set, a failed send or a lookup never flags it again. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the contact was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the contact last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "phoneNumber",
          "name",
          "email",
          "metadata",
          "optedOut",
          "optedOutAt",
          "optedOutKeyword",
          "optedInAt",
          "optedInMethod",
          "optedInSource",
          "lineType",
          "carrierName",
          "lineTypeCheckedAt",
          "invalidReason",
          "invalidatedAt",
          "userMarkedValidAt",
          "createdAt",
          "updatedAt"
        ],
        "description": "A contact as stored, in camelCase, as `POST /api/v1/contacts/{id}/mark-valid` returns it."
      },
      "ContactRemovedFromList": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "success"
        ]
      },
      "ContactWithLists": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Contact"
          },
          {
            "type": "object",
            "properties": {
              "lists": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The list's id."
                    },
                    "name": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name"
                  ]
                },
                "description": "The contact lists the contact belongs to."
              }
            },
            "required": [
              "lists"
            ]
          }
        ],
        "description": "A contact and the lists it belongs to, as `GET /api/v1/contacts/{id}` and `PATCH /api/v1/contacts/{id}` return it."
      },
      "ContactsAddedToList": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "added_count": {
            "type": "integer",
            "description": "How many memberships were added: one for every id that matches a contact of this workspace, even when that contact is already in the list. Ids that match no contact are not counted."
          }
        },
        "required": [
          "success",
          "added_count"
        ]
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The conversation's id."
          },
          "userId": {
            "type": "string",
            "description": "The account that owns the conversation."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace the conversation belongs to, if any."
          },
          "phoneNumber": {
            "type": "string",
            "description": "The contact's phone number in E.164 format, or a group key starting `grp_` for a group conversation."
          },
          "status": {
            "type": "string",
            "description": "`active` until the conversation is closed; an inbound message makes it `active` again. Known values: `active`, `closed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "active",
              "closed"
            ]
          },
          "unreadCount": {
            "type": "integer",
            "description": "Inbound messages since the conversation was last read."
          },
          "messageCount": {
            "type": "integer",
            "description": "Messages recorded in the conversation."
          },
          "lastMessageText": {
            "type": [
              "string",
              "null"
            ],
            "description": "The first 500 characters of the newest message. Always `null` for a test key."
          },
          "lastMessageAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the newest message was recorded. ISO 8601, in UTC."
          },
          "lastMessageDirection": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "inbound",
              "outbound",
              null
            ]
          },
          "channel": {
            "type": "string",
            "description": "The channel of the thread. An SMS and a WhatsApp thread with the same contact are two conversations. Known values: `sms`, `whatsapp`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "sms",
              "whatsapp"
            ]
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "Your own JSON object, set with `PATCH`. A group conversation also keeps `isGroup`, `groupKey` and `participants` here. `{}` by default; `null` only for a row stored without one, since the column allows it."
          },
          "tags": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Your own tags, set with `PATCH`. `[]` by default; `null` only for a row stored without them, since the column allows it."
          },
          "contactId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact linked to the conversation, if any."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the conversation was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the conversation last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "phoneNumber",
          "status",
          "unreadCount",
          "messageCount",
          "lastMessageText",
          "lastMessageAt",
          "lastMessageDirection",
          "channel",
          "metadata",
          "tags",
          "contactId",
          "createdAt",
          "updatedAt"
        ],
        "description": "A conversation as it is stored, which `PATCH`, close, reopen and mark-read return."
      },
      "ConversationContext": {
        "type": "object",
        "properties": {
          "context": {
            "type": "string",
            "description": "The thread as plain text for a language model: for a group, a first line naming its participants; then one line per message with text, `[YYYY-MM-DD HH:MM] Customer: ...` (`Customer <number>:` in a group) or `Business: ...`; then the newest inbound classification and the business, when known."
          },
          "conversation": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The conversation's id."
              },
              "phoneNumber": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "description": "`active` until the conversation is closed; an inbound message makes it `active` again. Known values: `active`, `closed`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "active",
                  "closed"
                ]
              },
              "messageCount": {
                "type": "integer"
              },
              "unreadCount": {
                "type": "integer"
              }
            },
            "required": [
              "id",
              "phoneNumber",
              "status",
              "messageCount",
              "unreadCount"
            ]
          },
          "tokenEstimate": {
            "type": "integer",
            "description": "`context`'s length divided by 4, rounded up."
          },
          "business": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "description": "The doing-business-as name, else the legal name."
              },
              "useCase": {
                "type": "string"
              }
            },
            "required": [
              "name"
            ],
            "description": "Present when the account has a business verification."
          }
        },
        "required": [
          "context",
          "conversation",
          "tokenEstimate"
        ]
      },
      "ConversationList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversationSummary"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/OffsetHasMorePagination"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "ConversationSummary": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Conversation"
          },
          {
            "type": "object",
            "properties": {
              "isGroup": {
                "type": "boolean",
                "description": "Whether this is a group conversation: `metadata.isGroup`, read as a boolean."
              },
              "participants": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Every member's phone number, for a group conversation: `metadata.participants`, as stored. Absent when metadata has none."
              }
            },
            "required": [
              "isGroup"
            ]
          }
        ],
        "description": "A conversation as `GET /api/v1/conversations` lists it."
      },
      "ConversationThreadMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "userId": {
            "type": "string",
            "description": "The account that owns the message."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ]
          },
          "apiKeyId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The API key that sent it, if any."
          },
          "to": {
            "type": "string"
          },
          "from": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "status": {
            "type": "string",
            "description": "The stored status, as `Message.status`."
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "errorCode": {
            "type": [
              "string",
              "null"
            ]
          },
          "retryCount": {
            "type": "integer"
          },
          "maxRetries": {
            "type": "integer"
          },
          "nextRetryAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the next retry is due. ISO 8601, in UTC."
          },
          "isSandbox": {
            "type": "boolean",
            "description": "Whether the message was simulated. A live key's thread leaves out messages stored as simulated, but lists one stored as live whose metadata says `simulated` with `true`; a test key's thread lists only messages stored as simulated."
          },
          "segments": {
            "type": "integer"
          },
          "creditsUsed": {
            "type": "integer"
          },
          "source": {
            "type": [
              "string",
              "null"
            ]
          },
          "messageType": {
            "type": "string"
          },
          "complianceStatus": {
            "type": [
              "string",
              "null"
            ]
          },
          "complianceDetails": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was created. ISO 8601, in UTC."
          },
          "sentAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the message was sent. ISO 8601, in UTC."
          },
          "deliveredAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the message was delivered. ISO 8601, in UTC."
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the message was deleted. ISO 8601, in UTC."
          },
          "batchId": {
            "type": [
              "string",
              "null"
            ]
          },
          "messageFormat": {
            "type": [
              "string",
              "null"
            ]
          },
          "mediaUrls": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "conversationId": {
            "type": [
              "string",
              "null"
            ]
          },
          "aiMetadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "failureDetail": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "Always `null` here: failure detail is internal."
          },
          "wamid": {
            "type": [
              "string",
              "null"
            ]
          },
          "waMessageType": {
            "type": [
              "string",
              "null"
            ]
          },
          "waTemplateId": {
            "type": [
              "string",
              "null"
            ]
          },
          "waBillingType": {
            "type": [
              "string",
              "null"
            ]
          },
          "readAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the message was read. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "apiKeyId",
          "to",
          "from",
          "text",
          "direction",
          "status",
          "error",
          "errorCode",
          "retryCount",
          "maxRetries",
          "nextRetryAt",
          "isSandbox",
          "segments",
          "creditsUsed",
          "source",
          "messageType",
          "complianceStatus",
          "complianceDetails",
          "metadata",
          "createdAt",
          "sentAt",
          "deliveredAt",
          "deletedAt",
          "batchId",
          "messageFormat",
          "mediaUrls",
          "conversationId",
          "aiMetadata",
          "failureDetail",
          "wamid",
          "waMessageType",
          "waTemplateId",
          "waBillingType",
          "readAt"
        ],
        "description": "A message of the thread, as it is stored: every column of the message row, including internal ones such as the carrier's own message id. Not the `Message` shape `GET /api/v1/messages` returns."
      },
      "ConversationWithMessages": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ConversationSummary"
          },
          {
            "type": "object",
            "properties": {
              "messages": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ConversationThreadMessage"
                    }
                  },
                  "pagination": {
                    "$ref": "#/components/schemas/OffsetHasMorePagination"
                  }
                },
                "required": [
                  "data",
                  "pagination"
                ],
                "description": "Present only with `include_messages=true`: every message of the key's account or workspace to or from this phone number, on any channel and whichever conversation it belongs to (for a group, every message carrying its group key), oldest first. A live key gets only live messages, a test key only simulated ones."
              }
            }
          }
        ],
        "description": "A conversation as `GET /api/v1/conversations` lists it."
      },
      "CountryList": {
        "type": "object",
        "properties": {
          "countries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CountryPricing"
            }
          },
          "tiers": {
            "$ref": "#/components/schemas/SmsPricingTiers"
          },
          "total_countries": {
            "type": "integer",
            "description": "How many countries `countries` holds."
          }
        },
        "required": [
          "countries",
          "tiers",
          "total_countries"
        ]
      },
      "CountryPricing": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "The country's ISO 3166-1 alpha-2 code, such as `GB`."
          },
          "name": {
            "type": "string",
            "description": "The country's English name."
          },
          "dial_code": {
            "type": "string",
            "description": "The country calling code with its `+`, such as `+44`."
          },
          "tier": {
            "type": "string",
            "description": "The price tier an SMS to this country is charged at. Known values: `domestic`, `tier1`, `tier2`, `tier3`, `tier4`, `tier5`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "domestic",
              "tier1",
              "tier2",
              "tier3",
              "tier4",
              "tier5"
            ]
          },
          "credits_per_sms": {
            "type": "integer",
            "description": "Credits one SMS segment to this country costs at the standard rate. 1 credit is $0.01. An enterprise account's own rates are not reflected."
          },
          "price_usd": {
            "type": "number",
            "description": "What one SMS segment to this country costs at the standard rate, in US dollars."
          },
          "requires_registration": {
            "type": "boolean",
            "description": "Whether sending to this country needs a sender registration first."
          },
          "alpha_sender": {
            "type": "string",
            "description": "Whether an alphanumeric sender ID reaches this country: `supported` as sent, `replaced` by a number on delivery, `partial` only partly, `registration_required` once the sender ID is registered, `unknown` when it is not documented. Known values: `supported`, `replaced`, `partial`, `registration_required`, `unknown`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "supported",
              "replaced",
              "partial",
              "registration_required",
              "unknown"
            ]
          }
        },
        "required": [
          "code",
          "name",
          "dial_code",
          "tier",
          "credits_per_sms",
          "price_usd",
          "requires_registration",
          "alpha_sender"
        ],
        "description": "A country Sendly sends SMS to, with its price tier, as `GET /api/v1/countries` lists it."
      },
      "CreateApiKeyRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "\\S",
            "description": "The key's name. Trimmed; must hold more than spaces."
          },
          "type": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "description": "Defaults to `test`. A `live` key needs a verified business and a positive credit balance."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "sms:send",
                "sms:read",
                "verify:send",
                "verify:read",
                "webhooks:read",
                "webhooks:write",
                "templates:read",
                "templates:write",
                "campaigns:read",
                "campaigns:write",
                "campaigns:send",
                "contacts:read",
                "contacts:write",
                "numbers:read",
                "numbers:write",
                "tendlc:read",
                "tendlc:write",
                "rcs:read",
                "rcs:write",
                "whatsapp:read",
                "whatsapp:write",
                "short_codes:read",
                "short_codes:write",
                "links:read",
                "links:write",
                "calls:read",
                "calls:write"
              ]
            },
            "description": "The new key's permissions, each one the calling key holds. Without it, the new key gets every grantable scope the calling key holds. A CLI session can grant any scope."
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key stops working, an ISO 8601 time in the future. Absent or `null` means never."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Read when `expiresAt` is absent or `null`."
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateAutoLabelRuleRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "conditions": {
            "type": "object",
            "properties": {
              "intent": {
                "anyOf": [
                  {
                    "type": "string",
                    "description": "An intent the message classifier gives an inbound message. Known values: `question`, `appointment`, `complaint`, `order_status`, `feedback`, `opt_out`, `greeting`, `confirmation`, `other`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "question",
                      "appointment",
                      "complaint",
                      "order_status",
                      "feedback",
                      "opt_out",
                      "greeting",
                      "confirmation",
                      "other"
                    ]
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "An intent the message classifier gives an inbound message. Known values: `question`, `appointment`, `complaint`, `order_status`, `feedback`, `opt_out`, `greeting`, `confirmation`, `other`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "question",
                        "appointment",
                        "complaint",
                        "order_status",
                        "feedback",
                        "opt_out",
                        "greeting",
                        "confirmation",
                        "other"
                      ]
                    },
                    "minItems": 1
                  }
                ],
                "description": "Match this intent, or any intent in the list. Absent matches every intent."
              },
              "sentiment": {
                "anyOf": [
                  {
                    "type": "string",
                    "description": "A sentiment the message classifier gives an inbound message. Known values: `positive`, `neutral`, `negative`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "positive",
                      "neutral",
                      "negative"
                    ]
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "A sentiment the message classifier gives an inbound message. Known values: `positive`, `neutral`, `negative`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "positive",
                        "neutral",
                        "negative"
                      ]
                    },
                    "minItems": 1
                  }
                ],
                "description": "Match this sentiment, or any sentiment in the list. Absent matches every sentiment."
              },
              "intentConfidenceMin": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Match only when the classifier is at least this sure of the intent, 0 to 1."
              },
              "sentimentConfidenceMin": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Match only when the classifier is at least this sure of the sentiment, 0 to 1."
              }
            },
            "additionalProperties": false,
            "description": "Every condition given must match. An empty object matches every classified inbound message. Any other field is refused with 400."
          },
          "actions": {
            "type": "object",
            "properties": {
              "addLabels": {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "description": "A label's id."
                },
                "description": "Labels to add to the conversation. An id that is not one of the workspace's labels is skipped when the rule runs. Stored as `[]` when absent."
              },
              "closeConversation": {
                "type": "boolean",
                "description": "`true` closes the conversation."
              }
            },
            "additionalProperties": false,
            "description": "What the rule does to the conversation when it matches. Any other field is refused with 400."
          },
          "priority": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -2147483648,
            "maximum": 2147483647,
            "description": "Rules run lowest first. Defaults to 0, which `null` also gives."
          }
        },
        "required": [
          "name",
          "conditions",
          "actions"
        ],
        "description": "`name`, `conditions` and `actions` are required, and checked against these types. `enabled` is ignored: a new rule is always enabled."
      },
      "CreateCallRequest": {
        "type": "object",
        "properties": {
          "to": {
            "type": "string",
            "description": "The number to call, in E.164 format. US and Canadian numbers only."
          },
          "agentId": {
            "type": "string",
            "description": "The workspace's AI agent that talks on the call. It must be switched on."
          },
          "from": {
            "type": "string",
            "description": "A voice-enabled number of the workspace to call from, with an emergency address registered. Optional when the workspace has one number that can place calls."
          },
          "context": {
            "type": "string",
            "maxLength": 2000,
            "description": "Up to 2,000 characters added to the agent's instructions for this call only, after trimming. Never returned."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "description": "Up to 20 string values, each up to 500 characters, keyed by 1 to 40 letters, digits, `_`, `.`, `:` or `-`. Returned on every read of the call and in its webhooks.",
            "maxProperties": 20
          }
        },
        "required": [
          "to",
          "agentId"
        ]
      },
      "CreateCampaignRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "The campaign's name, up to 255 characters."
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "The message. `{{name}}` and `{{brand_name}}` are filled in per recipient. An empty or blank text counts as none."
          },
          "messageText": {
            "type": [
              "string",
              "null"
            ],
            "description": "The same as `text`, and preferred over it when both are sent."
          },
          "templateId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Fill the message from a template of this workspace or a preset, when no text is sent. The template may use only `{{name}}` and `{{brand_name}}`."
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The same as `templateId`."
          },
          "contactListIds": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "maxItems": 1,
            "description": "The contact list to target, as a one-element array. More than one id answers 400; an empty array clears the list."
          },
          "contact_list_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "maxItems": 1,
            "description": "The same as `contactListIds`."
          },
          "contactListId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact list to target, as a single id."
          },
          "targetListId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact list to target. Takes precedence over the other list fields; `null` clears it."
          },
          "targetType": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "contact_list",
              "all_contacts",
              "manual",
              null
            ],
            "description": "Who to send to. Defaults to `contact_list`, which is also what any list field implies."
          },
          "manualRecipients": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "phone": {
                  "type": "string",
                  "description": "A phone number in E.164 format."
                },
                "name": {
                  "type": "string"
                }
              },
              "required": [
                "phone"
              ]
            },
            "description": "The recipients of a `manual` campaign."
          },
          "excludeOptedOut": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Stored only: opted-out contacts are always left out."
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Defaults to `America/New_York`."
          },
          "fromSender": {
            "type": [
              "string",
              "null"
            ],
            "description": "The number a scheduled send goes from. `POST /api/v1/campaigns/{id}/send` ignores it and uses its own `from`."
          },
          "channel": {
            "type": "string",
            "enum": [
              "sms"
            ],
            "description": "Campaigns are SMS only. Any other channel answers 400."
          }
        },
        "required": [
          "name"
        ],
        "description": "Send `name`, and the message as `text`, `messageText` or `templateId`. A `null` field counts as not sent. A `status` is never stored: a new campaign is always a draft."
      },
      "CreateContactListRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "\\S",
            "description": "The list's name. Trimmed, and it must not be blank."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "A description. An empty string is stored as `null`."
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateDraftRequest": {
        "type": "object",
        "properties": {
          "conversationId": {
            "type": "string",
            "minLength": 1,
            "description": "The conversation to reply to, from this workspace."
          },
          "text": {
            "type": "string",
            "minLength": 1,
            "description": "The reply to send."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Media URLs from `POST /api/v1/media`, sent as an MMS on approval."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object, passed to the message on approval. A message takes up to 4 KB."
          },
          "source": {
            "type": "string",
            "description": "Who wrote the draft, such as `ai` or `agent`. Defaults to `ai`."
          }
        },
        "required": [
          "conversationId",
          "text"
        ]
      },
      "CreateLabelRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "The label's name. Required."
          },
          "color": {
            "type": "string",
            "description": "Stored as sent, such as `#2563eb`. Nothing checks the format. An empty value means `#6b7280`."
          },
          "description": {
            "type": "string",
            "description": "Stored as sent. An empty value is stored as `null`."
          }
        },
        "required": [
          "name"
        ]
      },
      "CreatePortRequest": {
        "type": "object",
        "properties": {
          "portType": {
            "type": "string",
            "enum": [
              "full_port"
            ],
            "description": "Required, and only `full_port` is accepted."
          },
          "phoneNumber": {
            "type": "string",
            "pattern": "^\\+1(?:(?:800|833|844|855|866|877|888)\\d{7}|[2-9]\\d{2}[2-9]\\d{6})$",
            "description": "A US or Canada number in E.164 format, such as `+15555550100`, or a toll-free number. Trimmed before use."
          },
          "authPersonName": {
            "type": "string",
            "minLength": 1,
            "description": "The person who authorizes the port."
          },
          "authPersonEmail": {
            "type": "string",
            "minLength": 1,
            "description": "That person's email address. It is not checked for format."
          },
          "accountNumber": {
            "type": "string",
            "description": "The account number at the losing carrier. Needed to submit."
          },
          "serviceAddressLine1": {
            "type": "string"
          },
          "serviceAddressLine2": {
            "type": "string"
          },
          "serviceAddressCity": {
            "type": "string"
          },
          "serviceAddressState": {
            "type": "string"
          },
          "serviceAddressZip": {
            "type": "string"
          },
          "serviceAddressCountry": {
            "type": "string",
            "description": "Defaults to `US`."
          }
        },
        "required": [
          "portType",
          "phoneNumber",
          "authPersonName",
          "authPersonEmail"
        ]
      },
      "CreateRcsAgentRequest": {
        "type": "object",
        "properties": {
          "brandId": {
            "type": "string",
            "description": "The brand the agent belongs to."
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The agent's name. Takes precedence over `basics.displayName`."
          },
          "useCase": {
            "type": [
              "string",
              "null"
            ],
            "description": "Takes precedence over `basics.useCase`."
          },
          "basics": {
            "type": "object",
            "properties": {
              "displayName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "useCase": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "One of `MULTI_USE`, `PROMOTIONAL`, `TRANSACTIONAL`, `OTP`."
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "logoUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A public `https://` URL. Uploading is not available over the API."
              },
              "heroUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A public `https://` URL. Uploading is not available over the API."
              },
              "brandColor": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A hex color, such as `#2563EB`."
              },
              "privacyPolicyUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "termsAndConditionsUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "phoneNumber": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "number": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "website": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "email": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "address": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              }
            }
          },
          "campaign": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "companyOverview": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "agentOverview": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "additionalInformation": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "interactions": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "object",
                  "properties": {
                    "interactionType": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "messageExamples": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "consentSettings": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "callToAction": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "callToActionUrl": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "callToActionMediaUrl": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "A public `https://` URL. Uploading is not available over the API."
                  },
                  "doubleOptIn": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "doubleOptInMessage": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "optInMessage": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "helpResponse": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "optOutResponse": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "optInMethods": {
                    "type": [
                      "array",
                      "null"
                    ],
                    "items": {
                      "type": "object",
                      "properties": {
                        "methodType": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            },
            "description": "Merged into the stored campaign, one top-level field at a time. `null` clears it."
          },
          "testing": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "testUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "messageId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "additionalInformation": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "description": "Merged into the stored testing details. `null` clears them."
          }
        },
        "required": [
          "brandId"
        ],
        "description": "An agent draft. Its fields are checked when it is submitted for review."
      },
      "CreateRcsBrandRequest": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": [
              "string",
              "null"
            ]
          },
          "legalName": {
            "type": [
              "string",
              "null"
            ]
          },
          "legalEntityType": {
            "type": [
              "string",
              "null"
            ],
            "description": "One of `LIMITED_LIABILITY_COMPANY`, `SOLE_PROPRIETORSHIP`, `PARTNERSHIP`, `CORPORATION`, `S_CORPORATION`."
          },
          "organizationType": {
            "type": [
              "string",
              "null"
            ],
            "description": "One of `PRIVATE_PROFIT`, `PUBLIC_PROFIT`, `NON_PROFIT`, `GOVERNMENT`, `UNKNOWN`."
          },
          "websiteUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "ein": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nine digits, as `123456789` or `12-3456789`."
          },
          "stockSymbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "`EXCHANGE:SYMBOL`, for a public company."
          },
          "contact": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "firstName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "lastName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "phoneNumber": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "In E.164 format."
              }
            }
          },
          "address": {
            "type": "object",
            "properties": {
              "line1": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "line2": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "city": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "state": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "postalCode": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "countryCode": {
                "type": "string",
                "description": "`US`, in any case: the only country today."
              }
            },
            "required": [
              "countryCode"
            ]
          }
        },
        "required": [
          "address"
        ],
        "description": "A brand draft. Nothing but the country is checked until the agent is submitted for review. A field left out is stored empty."
      },
      "CreateTemplateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "\\S",
            "description": "The template's name. Trimmed."
          },
          "text": {
            "type": "string",
            "maxLength": 1600,
            "pattern": "\\S",
            "description": "The message text, up to 1,600 characters before trimming. Write variables as `{{key}}`, with letters, digits and underscores."
          },
          "variables": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "description": "The variable's name in the text."
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "string",
                    "number"
                  ],
                  "description": "Defaults to `string`."
                },
                "fallback": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "number"
                    }
                  ],
                  "description": "The value to use when a send gives none."
                }
              },
              "required": [
                "key"
              ]
            },
            "description": "Types and fallbacks for variables in the text, matched by `key`. Variables are always read from the text: an entry whose key is not in the text is dropped."
          }
        },
        "required": [
          "name",
          "text"
        ]
      },
      "CreateTenDlcBrandRequest": {
        "type": "object",
        "properties": {
          "legalName": {
            "type": "string",
            "minLength": 1,
            "description": "The legal business name."
          },
          "dba": {
            "type": "string",
            "description": "The \"doing business as\" name."
          },
          "ein": {
            "type": "string",
            "description": "The business registration number. Ignored for a sole proprietor."
          },
          "entityType": {
            "type": "string",
            "description": "Such as `PRIVATE_PROFIT` (the default), `PUBLIC_PROFIT`, `NON_PROFIT` or `SOLE_PROPRIETOR`."
          },
          "vertical": {
            "type": "string",
            "description": "The industry vertical."
          },
          "website": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "description": "The business contact email."
          },
          "phone": {
            "type": "string",
            "description": "The business phone number."
          },
          "mobilePhone": {
            "type": "string",
            "description": "A mobile number. Required for a sole proprietor, who receives a verification code on it."
          },
          "street": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "postalCode": {
            "type": "string"
          },
          "country": {
            "type": "string",
            "description": "An ISO 3166-1 alpha-2 code. Defaults to `US`."
          },
          "verificationId": {
            "type": "string",
            "description": "A Sendly verification to link the brand to."
          }
        },
        "required": [
          "legalName"
        ]
      },
      "CreateTenDlcCampaignRequest": {
        "type": "object",
        "properties": {
          "brandId": {
            "type": "string",
            "minLength": 1,
            "description": "A verified brand of this workspace."
          },
          "useCase": {
            "type": "string",
            "minLength": 1,
            "description": "The use case, such as `MIXED`. Replaced by `SOLE_PROPRIETOR` under a sole-proprietor brand."
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "description": "What the campaign sends and why."
          },
          "messageFlow": {
            "type": "string",
            "minLength": 1,
            "description": "How recipients opt in."
          },
          "sampleMessages": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "\\S"
            },
            "minItems": 2,
            "description": "Sample messages; the first five are kept. At least two, none blank and none with an unfilled placeholder."
          },
          "subUseCases": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "optInKeywords": {
            "type": "string"
          },
          "optOutKeywords": {
            "type": "string"
          },
          "helpKeywords": {
            "type": "string"
          },
          "optInMessage": {
            "type": "string"
          },
          "optOutMessage": {
            "type": "string"
          },
          "helpMessage": {
            "type": "string"
          },
          "embeddedLink": {
            "type": "boolean",
            "description": "Whether messages may hold links. Defaults to `true`."
          },
          "embeddedPhone": {
            "type": "boolean",
            "description": "Whether messages may hold phone numbers. Defaults to `false`."
          }
        },
        "required": [
          "brandId",
          "useCase",
          "description",
          "messageFlow",
          "sampleMessages"
        ]
      },
      "CreateVerifyProfileRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "\\S",
            "description": "Required, and not blank. Stored trimmed."
          },
          "template_id": {
            "type": "string",
            "description": "A template of this workspace, or a preset."
          },
          "app_name": {
            "type": "string"
          },
          "default_timeout_secs": {
            "type": "integer",
            "minimum": 60,
            "maximum": 3600,
            "description": "60 to 3,600. Defaults to 300, which 0 gives too."
          },
          "code_length": {
            "type": "integer",
            "minimum": 4,
            "maximum": 10,
            "description": "4 to 10. Defaults to 6, which 0 gives too."
          },
          "max_attempts": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "description": "1 to 10. Defaults to 3, which 0 gives too."
          },
          "allowed_countries": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Country codes, such as `US`, that codes may be sent to. Empty or absent allows every country."
          },
          "webhook_url": {
            "type": "string",
            "pattern": "^https:\\/\\/",
            "description": "An `https://` URL."
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateVerifySessionRequest": {
        "type": "object",
        "properties": {
          "success_url": {
            "type": "string",
            "pattern": "^(https:\\/\\/|http:\\/\\/(localhost|127\\.0\\.0\\.1)([:/?#]|$))",
            "description": "Where the hosted page sends the user after the code is checked. `https://`, or `http://localhost` or `127.0.0.1` for development."
          },
          "cancel_url": {
            "type": "string",
            "pattern": "^(https:\\/\\/|http:\\/\\/(localhost|127\\.0\\.0\\.1)([:/?#]|$))",
            "description": "Where the hosted page sends a user who cancels. The same rules as `success_url`."
          },
          "brand_name": {
            "type": "string",
            "description": "Defaults to the account's brand name, then its sender ID or business name."
          },
          "brand_color": {
            "type": "string",
            "pattern": "^#[0-9A-Fa-f]{6}$",
            "description": "A hex color, such as `#f59e0b`."
          },
          "brand_logo_url": {
            "type": "string"
          },
          "brand_background": {
            "type": "string"
          },
          "brand_accent": {
            "type": "string"
          },
          "border_radius": {
            "type": "string",
            "enum": [
              "none",
              "sm",
              "md",
              "lg",
              "xl",
              "full"
            ]
          },
          "font_family": {
            "type": "string",
            "enum": [
              "system",
              "inter",
              "roboto",
              "poppins"
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object, returned when the token is validated."
          }
        },
        "required": [
          "success_url"
        ],
        "description": "Each branding field left out takes the account's saved branding, when there is one."
      },
      "CreateVoiceAgentRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "description": "The agent's name, 1 to 80 characters after trimming."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the agent answers calls. Defaults to `true`."
          },
          "voice": {
            "type": "string",
            "maxLength": 120,
            "description": "A voice id from `GET /api/v1/voice/voices`. Missing, empty or unknown, the agent gets `ashley`, the default."
          },
          "language": {
            "type": "string",
            "maxLength": 16,
            "description": "A language tag such as `en-US`, up to 16 characters. Missing or empty, the voice's own language is used."
          },
          "greeting": {
            "type": "string",
            "maxLength": 500,
            "description": "What the agent says when it answers, up to 500 characters."
          },
          "instructions": {
            "type": "string",
            "maxLength": 4000,
            "description": "How the agent should handle a call, up to 4,000 characters."
          },
          "tools": {
            "type": "object",
            "properties": {
              "sendSms": {
                "type": "boolean",
                "description": "Whether the agent may text the caller. Defaults to `true`."
              },
              "transferTo": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 20,
                "pattern": "^$|^\\+[1-9]\\d{6,14}$",
                "description": "A number in E.164 format to transfer callers to when they ask for a person. An empty string or `null` removes it."
              },
              "backgroundAudio": {
                "type": "boolean",
                "description": "Whether the agent plays quiet background sound during a call. Defaults to `false`."
              }
            },
            "description": "What the agent can do during a call."
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateWebhookRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "minLength": 1,
            "description": "Where to post deliveries. `https://` is added when there is no protocol, and any other URL that does not start with `https://` is refused with 400 `invalid_url`. A test key may only use a URL that contains `localhost`, `127.0.0.1`, `.ngrok.`, `.loca.lt`, `webhook.site`, `.requestbin.` or `.pipedream.`."
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.sent",
                "message.delivered",
                "message.read",
                "message.failed",
                "message.bounced",
                "message.retrying",
                "message.received",
                "message.opt_out",
                "message.opt_in",
                "verification.created",
                "verification.delivered",
                "verification.verified",
                "verification.expired",
                "verification.failed",
                "verification.resent",
                "verification.delivery_failed",
                "conversation.created",
                "conversation.updated",
                "draft.created",
                "draft.approved",
                "draft.rejected",
                "contact.auto_flagged",
                "contact.marked_valid",
                "contacts.lookup_completed",
                "contacts.bulk_marked_valid",
                "brand.verified",
                "brand.failed",
                "campaign.approved",
                "campaign.rejected",
                "campaign.suspended",
                "assignment.confirmed",
                "assignment.failed",
                "rcs_brand.verified",
                "rcs_brand.failed",
                "rcs_agent.testing",
                "rcs_agent.live",
                "rcs_agent.rejected",
                "rcs_agent.action_required",
                "port.completed",
                "port_out.requested",
                "port_out.completed",
                "port_out.rejected",
                "port_out.cancelled",
                "number.activated",
                "number.failed",
                "number.requirements_required",
                "number.released",
                "whatsapp_account.connected",
                "whatsapp_account.failed",
                "whatsapp_template.approved",
                "whatsapp_template.rejected",
                "whatsapp_template.paused",
                "call.started",
                "call.completed",
                "call.recording.ready",
                "short_code.action_required",
                "short_code.rejected",
                "short_code.filed",
                "short_code.live",
                "short_code.suspended",
                "short_code.reactivated",
                "short_code.cancelled",
                "short_code.payment_succeeded",
                "short_code.payment_failed"
              ]
            },
            "minItems": 1,
            "description": "The events to subscribe to, at least one."
          },
          "description": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "all",
              "test",
              "live"
            ],
            "description": "Defaults to `all`. `live` needs a verified business. `all` and `test` both receive sandbox events."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object, stored with the webhook."
          }
        },
        "required": [
          "url",
          "events"
        ]
      },
      "CreateWhatsAppTemplateRequest": {
        "type": "object",
        "properties": {
          "sender": {
            "type": "string",
            "description": "The active WhatsApp sender whose business account gets the template."
          },
          "name": {
            "type": "string",
            "pattern": "^(?!test|sample|demo)[a-z0-9_]{1,512}$",
            "description": "Lower-case letters, digits and underscores, such as `order_shipped`. A name starting with `test`, `sample` or `demo` is refused."
          },
          "language": {
            "type": "string",
            "pattern": "\\S",
            "description": "The language code, such as `en_US`."
          },
          "category": {
            "type": "string",
            "enum": [
              "AUTHENTICATION",
              "UTILITY",
              "MARKETING"
            ],
            "description": "Matched ignoring case. It cannot be changed later."
          },
          "body": {
            "type": "string",
            "maxLength": 1024,
            "pattern": "\\S",
            "description": "The body text, up to 1,024 characters. Use `{{1}}`, `{{2}}` and so on for variables. Except in an `AUTHENTICATION` template, it cannot start or end with a variable."
          },
          "footer": {
            "type": "string",
            "maxLength": 60,
            "description": "A footer line, up to 60 characters."
          },
          "header": {
            "type": "string",
            "pattern": "^(?![\\s\\S]*\\{\\{\\s*\\d+\\s*\\}\\})",
            "description": "A fixed text header. A `{{n}}` variable in it is refused."
          },
          "buttons": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "url"
                      ],
                      "description": "Opens a link. Matched ignoring case."
                    },
                    "text": {
                      "type": "string",
                      "maxLength": 25,
                      "description": "The button's label, up to 25 characters."
                    },
                    "url": {
                      "type": "string",
                      "minLength": 1,
                      "description": "The link, which may hold a `{{1}}` variable."
                    },
                    "example": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Example values for the link's variable."
                    }
                  },
                  "required": [
                    "type",
                    "text",
                    "url"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "quick_reply"
                      ],
                      "description": "Sends its label back. Matched ignoring case."
                    },
                    "text": {
                      "type": "string",
                      "maxLength": 25,
                      "description": "The button's label, up to 25 characters."
                    }
                  },
                  "required": [
                    "type",
                    "text"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "otp"
                      ],
                      "description": "Copies a code. Required on an `AUTHENTICATION` template, where it is the only kind allowed besides `quick_reply`. Matched ignoring case."
                    },
                    "text": {
                      "type": "string",
                      "maxLength": 25,
                      "description": "The button's label, up to 25 characters. Defaults to `Copy code`."
                    }
                  },
                  "required": [
                    "type"
                  ]
                }
              ],
              "description": "A button: `url`, `quick_reply` or `otp`."
            },
            "maxItems": 3,
            "description": "Up to 3 buttons."
          },
          "examples": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "An example value for every body variable, by number: `{\"1\": \"A1234\"}`. Required when the body has variables."
          }
        },
        "required": [
          "sender",
          "name",
          "language",
          "category",
          "body"
        ]
      },
      "CreatedApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The new key's id."
          },
          "name": {
            "type": "string"
          },
          "key": {
            "type": "string",
            "description": "The full secret key. It is shown only here, once: store it securely."
          },
          "keyPrefix": {
            "type": [
              "string",
              "null"
            ],
            "description": "The key's first 12 characters."
          },
          "type": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "description": "`test` simulates every send and never charges; `live` sends."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was created. ISO 8601, in UTC."
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key stops working. ISO 8601, in UTC."
          },
          "apiKey": {
            "$ref": "#/components/schemas/ApiKey"
          }
        },
        "required": [
          "id",
          "name",
          "key",
          "keyPrefix",
          "type",
          "createdAt",
          "expiresAt",
          "apiKey"
        ],
        "description": "A new key with its secret, and the same key as the list shows it."
      },
      "CreditBalance": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "integer",
            "description": "The credit balance. 1 credit is US$0.01. It can be negative: inbound messages and calls are charged even when the balance has run out, and a pooled enterprise pool's balance runs negative down to its overage cap, the negative part being accrued overage."
          },
          "reservedBalance": {
            "type": "integer",
            "description": "Credits held for messages that are scheduled or still being sent."
          },
          "availableBalance": {
            "type": "integer",
            "description": "Credits that can be spent now. For `prepaid`, `balance` minus `reservedBalance`, which is not floored at 0. For `pooled`, `balance` plus the pool's overage cap minus `reservedBalance`, floored at 0."
          },
          "billingMode": {
            "type": "string",
            "enum": [
              "prepaid",
              "pooled"
            ],
            "description": "`pooled` when the key's workspace is owned by a user whose active enterprise account shares one credit pool, so the numbers are the pool's. `prepaid` otherwise, with the workspace's own balance, or the account's own for a key with no workspace, even when that account's enterprise account shares a pool."
          }
        },
        "required": [
          "balance",
          "reservedBalance",
          "availableBalance",
          "billingMode"
        ],
        "description": "A credit balance. A `prepaid` balance is all zeros when the workspace has no credit balance yet."
      },
      "CreditTransaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The transaction's id."
          },
          "amount": {
            "type": "integer",
            "description": "Credits in (positive) or out (negative)."
          },
          "balance_after": {
            "type": "integer",
            "description": "The balance after the transaction. 0 when the transaction recorded no balance."
          },
          "type": {
            "type": "string",
            "description": "What moved the credits. An auto-recharge is recorded as `purchase`. `fee` is a monthly fee taken from credits, such as a toll-free number's fee for a month under 50 messages. `gift` appears only on older transactions. Known values: `purchase`, `usage`, `refund`, `bonus`, `transfer`, `admin_grant`, `admin_seed`, `gift`, `fee`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "purchase",
              "usage",
              "refund",
              "bonus",
              "transfer",
              "admin_grant",
              "admin_seed",
              "gift",
              "fee"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the transaction was for, in plain English."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the transaction was recorded. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "amount",
          "balance_after",
          "type",
          "description",
          "created_at"
        ]
      },
      "CreditTransactionList": {
        "type": "object",
        "properties": {
          "transactions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditTransaction"
            }
          }
        },
        "required": [
          "transactions"
        ],
        "description": "A page of transactions, newest first, with no paging fields: a page shorter than `limit` is the last one."
      },
      "CreditTransferResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "amount": {
            "type": "integer",
            "description": "The credits moved, as sent."
          },
          "sourceBalance": {
            "type": "integer",
            "description": "The key's workspace's balance after the transfer."
          },
          "targetBalance": {
            "type": "integer",
            "description": "The target workspace's balance after the transfer."
          }
        },
        "required": [
          "success",
          "amount",
          "sourceBalance",
          "targetBalance"
        ]
      },
      "DeleteAutoLabelRuleResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "success"
        ]
      },
      "DeletedVoiceAgent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The removed agent's id."
          },
          "object": {
            "type": "string",
            "enum": [
              "voice_agent"
            ]
          },
          "deleted": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "id",
          "object",
          "deleted"
        ]
      },
      "DepositPoolCreditsRequest": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "description": "Credits to add to the pool, a whole number above 0."
          },
          "description": {
            "type": "string",
            "description": "Recorded on the credit transaction. Defaults to `API pool deposit`."
          }
        },
        "required": [
          "amount"
        ]
      },
      "DisposableEmailError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "disposable_email"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "disposable_email",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "disposable_email"
        ]
      },
      "EnhanceMessageFallback": {
        "type": "object",
        "properties": {
          "enhanced": {
            "type": "string",
            "description": "The `text` sent, unchanged and not shortened, or an empty string when none was."
          },
          "explanation": {
            "type": "string",
            "enum": [
              ""
            ],
            "description": "Always empty."
          }
        },
        "required": [
          "enhanced",
          "explanation"
        ]
      },
      "EnhanceMessageRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The draft to rewrite. Only its first 500 characters are read. Optional when `messageType` is set: the message is then written from scratch."
          },
          "messageType": {
            "type": "string",
            "maxLength": 50,
            "description": "What kind of message this is, such as `marketing` or `transactional`, to steer the rewrite. At most 50 characters. Optional when `text` is set."
          }
        },
        "description": "At least one of `text` and `messageType` must be set and not empty."
      },
      "EnhancedMessage": {
        "type": "object",
        "properties": {
          "enhanced": {
            "type": "string",
            "maxLength": 160,
            "description": "The rewritten message, at most 160 characters."
          },
          "explanation": {
            "type": "string",
            "description": "What the rewrite changed, in the model's own words."
          },
          "model": {
            "type": "string",
            "description": "The id of the model that wrote the rewrite."
          }
        },
        "required": [
          "enhanced",
          "explanation",
          "model"
        ]
      },
      "EnterpriseAccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The enterprise account's id."
          },
          "maxWorkspaces": {
            "type": "integer",
            "description": "How many workspaces the account may have."
          },
          "workspaceCount": {
            "type": "integer",
            "description": "How many team workspaces the key's owner owns."
          },
          "workspaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnterpriseAccountWorkspace"
            },
            "description": "Every team workspace the key's owner holds the owner role in, with no paging."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The account's stored settings, as kept, except the webhook signing secret: such as `webhookUrl`, `webhookEvents`, `webhookWorkspaces` and `autoTopUp`, and any billing settings the account has."
          }
        },
        "required": [
          "id",
          "maxWorkspaces",
          "workspaceCount",
          "workspaces",
          "metadata"
        ]
      },
      "EnterpriseAccountWebhook": {
        "type": "object",
        "properties": {
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The webhook URL. `null` when none is set, or it was deleted."
          },
          "events": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "The event types sent to the webhook. `null` when it was never set; `null` and an empty list both mean every event."
          },
          "workspaces": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "The workspace ids whose events are sent. `null` when it was never set; `null` and an empty list both mean every workspace."
          }
        },
        "required": [
          "url",
          "events",
          "workspaces"
        ]
      },
      "EnterpriseAccountWebhookSecret": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "secret": {
            "type": "string",
            "description": "The new signing secret, 64 hex characters. Shown once."
          },
          "rotated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the secret was replaced. ISO 8601, in UTC."
          },
          "message": {
            "type": "string",
            "enum": [
              "Webhook signing secret rotated. Save this secret - it won't be shown again."
            ]
          }
        },
        "required": [
          "success",
          "secret",
          "rotated_at",
          "message"
        ]
      },
      "EnterpriseAccountWebhookSet": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "events": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "The event types sent to the webhook. `null` when it was never set; `null` and an empty list both mean every event."
          },
          "workspaces": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "The workspace ids whose events are sent. `null` when it was never set; `null` and an empty list both mean every workspace."
          },
          "signingSecret": {
            "type": "string",
            "description": "The signing secret, 64 hex characters. Present only when this call created it: on the account's first registration. Later calls, even after a delete, keep the secret and leave it out."
          }
        },
        "required": [
          "url",
          "events",
          "workspaces"
        ]
      },
      "EnterpriseAccountWebhookTest": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean",
                "description": "Whether the endpoint answered 2xx."
              },
              "statusCode": {
                "type": "integer",
                "description": "The status the endpoint answered."
              },
              "statusText": {
                "type": "string",
                "description": "The endpoint's status text, which can be empty."
              }
            },
            "required": [
              "success",
              "statusCode",
              "statusText"
            ],
            "title": "The endpoint answered"
          },
          {
            "type": "object",
            "properties": {
              "success": {
                "type": "boolean",
                "enum": [
                  false
                ]
              },
              "error": {
                "type": "string",
                "description": "Why the request failed: `Request timed out (10s)`, or the network error's own message."
              }
            },
            "required": [
              "success",
              "error"
            ],
            "title": "The endpoint could not be reached"
          }
        ]
      },
      "EnterpriseAccountWorkspace": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The workspace's id."
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "description": "The workspace's status. Known values: `active`, `suspended`, `provision_failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "active",
              "suspended",
              "provision_failed"
            ]
          },
          "suspendedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the workspace was suspended. ISO 8601, in UTC."
          },
          "verificationStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace's verification status: `pending_review` while Sendly holds it for review, `submitted` once it is sent to the carrier, `processing` while the carrier reviews it, `action_required` when the carrier needs something from you, and `approved` for an international sender ID. `null` when the workspace has no verification. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `processing`, `action_required`, `verified`, `approved`, `rejected`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "pending",
              "pending_review",
              "submitted",
              "in_progress",
              "processing",
              "action_required",
              "verified",
              "approved",
              "rejected"
            ]
          },
          "rejectionReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the verification was rejected, when it was."
          },
          "verificationType": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the verification covers. `null` when the workspace has no verification. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "toll_free",
              "international",
              "both"
            ]
          },
          "tollFreeNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace's toll-free number, in E.164 format, once it has one."
          },
          "creditBalance": {
            "type": "integer",
            "description": "The workspace's own credit balance. 0 when it has no credit record."
          },
          "monthlyMessageQuota": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The monthly message cap. `null` when there is none, or it is 0."
          },
          "messagesThisMonth": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "status",
          "suspendedAt",
          "verificationStatus",
          "rejectionReason",
          "verificationType",
          "tollFreeNumber",
          "creditBalance",
          "monthlyMessageQuota",
          "messagesThisMonth"
        ]
      },
      "EnterpriseAnalyticsOverview": {
        "type": "object",
        "properties": {
          "totalWorkspaces": {
            "type": "integer",
            "description": "How many team workspaces the key's owner belongs to, in any role."
          },
          "totalMessages": {
            "type": "integer",
            "description": "Every message those workspaces have, all time."
          },
          "totalDelivered": {
            "type": "integer"
          },
          "totalFailed": {
            "type": "integer"
          },
          "deliveryRate": {
            "type": "number",
            "description": "`totalDelivered` as a percentage of `totalMessages`, to two decimals."
          },
          "totalCredits": {
            "type": "integer",
            "description": "Their credit balances, summed."
          },
          "deliveredMessages": {
            "type": "integer",
            "description": "Same as `totalDelivered`."
          },
          "failedMessages": {
            "type": "integer",
            "description": "Same as `totalFailed`."
          },
          "totalCreditsUsed": {
            "type": "integer",
            "description": "Credits spent on usage by those workspaces, all time."
          },
          "activeWorkspaces": {
            "type": "integer"
          },
          "suspendedWorkspaces": {
            "type": "integer"
          },
          "totalMessagesSent": {
            "type": "integer",
            "description": "Same as `totalMessages`."
          },
          "totalMessagesDelivered": {
            "type": "integer",
            "description": "Same as `totalDelivered`."
          },
          "totalCreditsRemaining": {
            "type": "integer",
            "description": "Same as `totalCredits`."
          }
        },
        "required": [
          "totalWorkspaces",
          "totalMessages",
          "totalDelivered",
          "totalFailed",
          "deliveryRate",
          "totalCredits",
          "deliveredMessages",
          "failedMessages",
          "totalCreditsUsed",
          "activeWorkspaces",
          "suspendedWorkspaces",
          "totalMessagesSent",
          "totalMessagesDelivered",
          "totalCreditsRemaining"
        ]
      },
      "EnterpriseAutoTopUp": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "threshold": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              },
              {
                "type": "boolean",
                "enum": [
                  true
                ]
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "object",
                "additionalProperties": {}
              }
            ],
            "description": "The balance, a number, that a workspace falls below to trigger a top-up. 0 when left out or sent empty. Stored as sent: the server checks no type, so a value saved as documented comes back as described, but any other value that is not empty, `0`, `false` or `null` comes back as it was sent, such as the string `\"500\"`."
          },
          "amount": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              },
              {
                "type": "boolean",
                "enum": [
                  true
                ]
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "object",
                "additionalProperties": {}
              }
            ],
            "description": "Credits moved per top-up, a number. 0 when left out or sent empty. Stored as sent: the server checks no type, so a value saved as documented comes back as described, but any other value that is not empty, `0`, `false` or `null` comes back as it was sent, such as the string `\"500\"`."
          },
          "sourceWorkspaceId": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              },
              {
                "type": "boolean",
                "enum": [
                  true
                ]
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "object",
                "additionalProperties": {}
              },
              {
                "type": "null"
              },
              {
                "type": "null"
              }
            ],
            "description": "The workspace credits are moved from, a string, or `null` when it was left out or sent empty. A top-up with no source workspace never runs. It is checked only when `enabled` is `true`. Stored as sent: the server checks no type, so a value saved as documented comes back as described, but any other value that is not empty, `0`, `false` or `null` comes back as it was sent, such as the string `\"500\"`."
          }
        },
        "required": [
          "enabled",
          "threshold",
          "amount",
          "sourceWorkspaceId"
        ]
      },
      "EnterpriseBillingBreakdown": {
        "type": "object",
        "properties": {
          "period": {
            "type": "string",
            "enum": [
              "7d",
              "30d",
              "90d"
            ]
          },
          "includedWorkspaces": {
            "type": "integer",
            "description": "How many workspaces the plan includes without a fee."
          },
          "summary": {
            "type": "object",
            "properties": {
              "platformFee": {
                "type": "number",
                "description": "The platform fee for the account. In US cents."
              },
              "totalWorkspaceFees": {
                "type": "number",
                "description": "The per-workspace fee times the workspaces that pay it. In US cents."
              },
              "totalCreditsUsed": {
                "type": "integer",
                "description": "Credits used by every workspace the key's owner owns, summed, whatever page of `workspaces` is returned."
              },
              "totalCost": {
                "type": "number",
                "description": "`platformFee` plus `totalWorkspaceFees` plus `totalCreditsUsed`."
              }
            },
            "required": [
              "platformFee",
              "totalWorkspaceFees",
              "totalCreditsUsed",
              "totalCost"
            ]
          },
          "workspaces": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The workspace's id."
                },
                "name": {
                  "type": "string"
                },
                "creditsUsed": {
                  "type": "integer",
                  "description": "Credits spent on usage in the period."
                },
                "creditsPurchased": {
                  "type": "integer"
                },
                "creditsTransferredIn": {
                  "type": "integer"
                },
                "creditsTransferredOut": {
                  "type": "integer"
                },
                "messagesSent": {
                  "type": "integer",
                  "description": "Messages created in the period, in any status."
                },
                "messagesDelivered": {
                  "type": "integer"
                },
                "workspaceFee": {
                  "type": "number",
                  "description": "The workspace's fee: 0 when it is one of the included workspaces. In US cents."
                },
                "included": {
                  "type": "boolean",
                  "description": "Whether the workspace is one of the included ones, which have no fee. Always `false` with batch pricing."
                },
                "allocatedPlatformFee": {
                  "type": "number",
                  "description": "The platform fee divided evenly across the workspaces, rounded. In US cents."
                },
                "totalCost": {
                  "type": "number",
                  "description": "`creditsUsed` plus `workspaceFee` plus `allocatedPlatformFee`."
                }
              },
              "required": [
                "id",
                "name",
                "creditsUsed",
                "creditsPurchased",
                "creditsTransferredIn",
                "creditsTransferredOut",
                "messagesSent",
                "messagesDelivered",
                "workspaceFee",
                "included",
                "allocatedPlatformFee",
                "totalCost"
              ]
            },
            "description": "Every team workspace the key's owner holds the owner role in, or one page of them when both `page` and `limit` are set."
          }
        },
        "required": [
          "period",
          "includedWorkspaces",
          "summary",
          "workspaces"
        ]
      },
      "EnterpriseBulkProvisionResult": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "success",
                        "partial"
                      ],
                      "description": "`partial` when the workspace was created but its credits could not be moved."
                    },
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "workspaceId": {
                      "type": "string",
                      "description": "The new workspace's id."
                    },
                    "slug": {
                      "type": "string"
                    },
                    "warning": {
                      "type": "string",
                      "description": "Why the credits were not moved, as `Credit transfer failed: Insufficient credits`."
                    }
                  },
                  "required": [
                    "name",
                    "status",
                    "success",
                    "workspaceId",
                    "slug"
                  ],
                  "title": "Workspace created"
                },
                {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The name as sent."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "failed"
                      ]
                    },
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string",
                      "description": "Why the workspace was not created. Known values: `name is required`, `Workspace with similar name exists`, `Workspace creation failed`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "name is required",
                        "Workspace with similar name exists",
                        "Workspace creation failed"
                      ]
                    }
                  },
                  "required": [
                    "status",
                    "success",
                    "error"
                  ],
                  "title": "Workspace not created"
                }
              ]
            }
          },
          "summary": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              },
              "succeeded": {
                "type": "integer"
              },
              "failed": {
                "type": "integer"
              }
            },
            "required": [
              "total",
              "succeeded",
              "failed"
            ]
          },
          "totalRequested": {
            "type": "integer"
          },
          "totalCreated": {
            "type": "integer"
          },
          "totalFailed": {
            "type": "integer"
          }
        },
        "required": [
          "results",
          "summary",
          "totalRequested",
          "totalCreated",
          "totalFailed"
        ]
      },
      "EnterpriseCreditAnalytics": {
        "type": "object",
        "properties": {
          "period": {
            "type": "string",
            "description": "The `period` query parameter as sent, or `30d` when it was left out. A value other than `7d`, `30d` or `90d` is echoed as is."
          },
          "totalBalance": {
            "type": "integer",
            "description": "The credit balance of every team workspace the key's owner belongs to, summed."
          },
          "totalLifetime": {
            "type": "integer",
            "description": "Every credit those workspaces have ever received, summed."
          },
          "totalUsed": {
            "type": "integer",
            "description": "`totalLifetime` less `totalBalance`."
          },
          "workspaceCount": {
            "type": "integer",
            "description": "How many team workspaces the key's owner belongs to, in any role."
          }
        },
        "required": [
          "period",
          "totalBalance",
          "totalLifetime",
          "totalUsed",
          "workspaceCount"
        ]
      },
      "EnterpriseCreditsNotPooled": {
        "type": "object",
        "properties": {
          "pooled": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "message": {
            "type": "string",
            "enum": [
              "Enterprise account uses per-workspace credits"
            ]
          }
        },
        "required": [
          "pooled",
          "message"
        ],
        "title": "Per-workspace credits"
      },
      "EnterpriseCustomDomainSetup": {
        "type": "object",
        "properties": {
          "domain": {
            "type": "string",
            "description": "The domain, in lower case."
          },
          "verified": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "dnsInstructions": {
            "type": "object",
            "properties": {
              "cname": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "CNAME"
                    ]
                  },
                  "name": {
                    "type": "string"
                  },
                  "value": {
                    "type": "string",
                    "description": "Always `sendly.live`."
                  }
                },
                "required": [
                  "type",
                  "name",
                  "value"
                ]
              },
              "txt": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "TXT"
                    ]
                  },
                  "name": {
                    "type": "string",
                    "description": "`_sendly-verify.` and the domain."
                  },
                  "value": {
                    "type": "string",
                    "description": "The verification token."
                  }
                },
                "required": [
                  "type",
                  "name",
                  "value"
                ]
              }
            },
            "required": [
              "cname",
              "txt"
            ]
          }
        },
        "required": [
          "domain",
          "verified",
          "dnsInstructions"
        ]
      },
      "EnterpriseDeliveryAnalyticsItem": {
        "type": "object",
        "properties": {
          "workspaceId": {
            "type": "string",
            "description": "The workspace's id."
          },
          "workspaceName": {
            "type": "string"
          },
          "totalMessages": {
            "type": "integer",
            "description": "Every message the workspace has, all time."
          },
          "delivered": {
            "type": "integer"
          },
          "deliveryRate": {
            "type": "number",
            "description": "`delivered` as a percentage of `totalMessages`, to two decimals. 0 with no messages."
          },
          "name": {
            "type": "string",
            "description": "Same as `workspaceName`."
          },
          "sent": {
            "type": "integer",
            "description": "Same as `totalMessages`."
          },
          "failed": {
            "type": "integer"
          },
          "rate": {
            "type": "integer",
            "description": "`deliveryRate` rounded to a whole number. 0 with no messages."
          }
        },
        "required": [
          "workspaceId",
          "workspaceName",
          "totalMessages",
          "delivered",
          "deliveryRate",
          "name",
          "sent",
          "failed",
          "rate"
        ]
      },
      "EnterpriseMessageAnalytics": {
        "type": "object",
        "properties": {
          "period": {
            "type": "string",
            "description": "The `period` query parameter as sent, or `30d` when it was left out. A value other than `7d`, `30d` or `90d` is echoed as is."
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "description": "The day, as `YYYY-MM-DD`."
                },
                "sent": {
                  "type": "integer",
                  "description": "Messages created that day, in any status."
                },
                "delivered": {
                  "type": "integer"
                },
                "failed": {
                  "type": "integer"
                }
              },
              "required": [
                "date",
                "sent",
                "delivered",
                "failed"
              ]
            },
            "description": "One row per day of the period, oldest first, days with no messages included as zeros. Empty with no team workspaces."
          }
        },
        "required": [
          "period",
          "data"
        ]
      },
      "EnterpriseOptInPage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The page's id."
          },
          "userId": {
            "type": "string",
            "description": "The user who owns the page."
          },
          "organizationId": {
            "type": "string",
            "description": "The workspace's id."
          },
          "verificationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The verification the page was made for."
          },
          "slug": {
            "type": "string"
          },
          "pageType": {
            "type": "string",
            "description": "What the page is. Known values: `opt_in`, `privacy`, `terms`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "opt_in",
              "privacy",
              "terms"
            ]
          },
          "businessName": {
            "type": "string"
          },
          "useCase": {
            "type": [
              "string",
              "null"
            ]
          },
          "useCaseSummary": {
            "type": [
              "string",
              "null"
            ]
          },
          "sampleMessages": {
            "type": [
              "string",
              "null"
            ]
          },
          "effectiveDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The date a privacy or terms page takes effect. ISO 8601, in UTC."
          },
          "businessAddress": {
            "type": [
              "string",
              "null"
            ]
          },
          "contactEmail": {
            "type": [
              "string",
              "null"
            ]
          },
          "contactPhone": {
            "type": [
              "string",
              "null"
            ]
          },
          "socialUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "logoUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "headerColor": {
            "type": [
              "string",
              "null"
            ]
          },
          "buttonColor": {
            "type": [
              "string",
              "null"
            ]
          },
          "customHeadline": {
            "type": [
              "string",
              "null"
            ]
          },
          "customBenefits": {
            "description": "What was last sent as `customBenefits`, stored as is: usually an array of strings, `null` when never set."
          },
          "customConsentText": {
            "type": [
              "string",
              "null"
            ]
          },
          "screenshotUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "screenshotCapturedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the screenshot was taken. ISO 8601, in UTC."
          },
          "isActive": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "viewCount": {
            "type": [
              "integer",
              "null"
            ]
          },
          "customDomain": {
            "type": [
              "string",
              "null"
            ]
          },
          "domainVerified": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "domainVerificationToken": {
            "type": [
              "string",
              "null"
            ],
            "description": "The value the custom domain's `_sendly-verify` TXT record must hold."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the page was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the page was last changed. Setting a custom domain moves it; customizing the page does not. ISO 8601, in UTC."
          },
          "url": {
            "type": "string",
            "description": "The page's public address, `https://sendly.live/opt-in/{slug}`."
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "verificationId",
          "slug",
          "pageType",
          "businessName",
          "useCase",
          "useCaseSummary",
          "sampleMessages",
          "effectiveDate",
          "businessAddress",
          "contactEmail",
          "contactPhone",
          "socialUrl",
          "logoUrl",
          "headerColor",
          "buttonColor",
          "customHeadline",
          "customBenefits",
          "customConsentText",
          "screenshotUrl",
          "screenshotCapturedAt",
          "isActive",
          "viewCount",
          "customDomain",
          "domainVerified",
          "domainVerificationToken",
          "createdAt",
          "updatedAt",
          "url"
        ],
        "description": "Every stored field of the page, with `url`."
      },
      "EnterpriseOptInPageCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The page's id."
          },
          "slug": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "The page's public address, `https://sendly.live/opt-in/{slug}`."
          },
          "businessName": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "slug",
          "url",
          "businessName"
        ]
      },
      "EnterpriseOptInPageListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The page's id."
          },
          "slug": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "The page's public address, `https://sendly.live/opt-in/{slug}`."
          },
          "businessName": {
            "type": "string"
          },
          "useCase": {
            "type": [
              "string",
              "null"
            ]
          },
          "isActive": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "viewCount": {
            "type": [
              "integer",
              "null"
            ]
          },
          "logoUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "headerColor": {
            "type": [
              "string",
              "null"
            ]
          },
          "buttonColor": {
            "type": [
              "string",
              "null"
            ]
          },
          "customHeadline": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the page was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "slug",
          "url",
          "businessName",
          "useCase",
          "isActive",
          "viewCount",
          "logoUrl",
          "headerColor",
          "buttonColor",
          "customHeadline",
          "createdAt"
        ]
      },
      "EnterprisePoolCredits": {
        "type": "object",
        "properties": {
          "pooled": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "balance": {
            "type": "integer",
            "description": "The pool's balance. It can be negative, down to the account's overage cap: the negative part is overage owed."
          },
          "lifetimeCredits": {
            "type": "integer",
            "description": "Every credit ever deposited into the pool."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the pool last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "pooled",
          "balance",
          "lifetimeCredits",
          "updatedAt"
        ],
        "title": "Pooled credits"
      },
      "EnterprisePoolDeposit": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "integer",
            "description": "The pool's balance after the deposit."
          },
          "lifetimeCredits": {
            "type": "integer"
          },
          "deposited": {
            "type": "integer",
            "description": "The `amount` deposited."
          }
        },
        "required": [
          "balance",
          "lifetimeCredits",
          "deposited"
        ]
      },
      "EnterpriseProvisionResult": {
        "type": "object",
        "properties": {
          "workspace": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The workspace's id."
              },
              "name": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "slug"
            ]
          },
          "verification": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The verification's id."
                  },
                  "status": {
                    "type": "string",
                    "description": "The verification's status. `processing` means the carrier is reviewing it, `action_required` that it needs changes from you. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `processing`, `action_required`, `verified`, `rejected`, `archived`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "pending",
                      "pending_review",
                      "submitted",
                      "in_progress",
                      "processing",
                      "action_required",
                      "verified",
                      "rejected",
                      "archived"
                    ]
                  },
                  "type": {
                    "type": "string",
                    "description": "What the verification covers. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "toll_free",
                      "international",
                      "both"
                    ]
                  },
                  "tollFreeNumber": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The workspace's toll-free number in E.164 format, or `null` before one is set."
                  },
                  "inherited": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  }
                },
                "required": [
                  "id",
                  "status",
                  "type",
                  "tollFreeNumber",
                  "inherited"
                ],
                "title": "Verification shared"
              },
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The verification's id."
                  },
                  "status": {
                    "type": "string",
                    "description": "The verification's status. `processing` means the carrier is reviewing it, `action_required` that it needs changes from you. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `processing`, `action_required`, `verified`, `rejected`, `archived`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "pending",
                      "pending_review",
                      "submitted",
                      "in_progress",
                      "processing",
                      "action_required",
                      "verified",
                      "rejected",
                      "archived"
                    ]
                  },
                  "type": {
                    "type": "string",
                    "description": "What the verification covers. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "toll_free",
                      "international",
                      "both"
                    ]
                  },
                  "tollFreeNumber": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The workspace's toll-free number in E.164 format, or `null` before one is set."
                  },
                  "inherited": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  },
                  "newNumber": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  },
                  "businessName": {
                    "type": "string"
                  },
                  "useCase": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "id",
                  "status",
                  "type",
                  "tollFreeNumber",
                  "inherited",
                  "newNumber",
                  "businessName",
                  "useCase"
                ],
                "title": "Verification copied, with a new number"
              },
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The verification's id."
                  },
                  "status": {
                    "type": "string",
                    "description": "The verification's status. `processing` means the carrier is reviewing it, `action_required` that it needs changes from you. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `processing`, `action_required`, `verified`, `rejected`, `archived`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "pending",
                      "pending_review",
                      "submitted",
                      "in_progress",
                      "processing",
                      "action_required",
                      "verified",
                      "rejected",
                      "archived"
                    ]
                  },
                  "tollFreeNumber": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The workspace's toll-free number in E.164 format, or `null` before one is set."
                  },
                  "inherited": {
                    "type": "boolean",
                    "enum": [
                      false
                    ]
                  }
                },
                "required": [
                  "id",
                  "status",
                  "tollFreeNumber",
                  "inherited"
                ],
                "title": "Verification created"
              }
            ]
          },
          "optInPage": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The page's id."
                  },
                  "slug": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "slug",
                  "url"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "error": {
                    "type": "string",
                    "description": "Why the page could not be created."
                  }
                },
                "required": [
                  "error"
                ],
                "title": "Opt-in page failed"
              }
            ],
            "description": "Absent when `generateOptInPage` is `false`."
          },
          "legalPages": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "privacyUrl": {
                    "type": "string"
                  },
                  "termsUrl": {
                    "type": "string"
                  },
                  "privacyPageId": {
                    "type": "string",
                    "description": "The privacy page's id."
                  },
                  "termsPageId": {
                    "type": "string",
                    "description": "The terms page's id."
                  }
                },
                "required": [
                  "privacyUrl",
                  "termsUrl",
                  "privacyPageId",
                  "termsPageId"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "error": {
                    "type": "string",
                    "description": "Why the page could not be created."
                  }
                },
                "required": [
                  "error"
                ],
                "title": "Legal pages failed"
              }
            ],
            "description": "Absent when `generateOptInPage` is `false`."
          },
          "businessPage": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The page's id."
                  },
                  "slug": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "slug",
                  "url"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "error": {
                    "type": "string",
                    "description": "Why the page could not be created."
                  }
                },
                "required": [
                  "error"
                ],
                "title": "Business page failed"
              }
            ],
            "description": "Present when a hosted business page was asked for."
          },
          "credits": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "transferred": {
                    "type": "integer"
                  },
                  "balance": {
                    "type": "integer"
                  }
                },
                "required": [
                  "transferred",
                  "balance"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "error": {
                    "type": "string"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "Credit transfer failed"
              }
            ],
            "description": "Present when credits were moved, or the move failed. Absent when the credit source is not the key owner's."
          },
          "key": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The key's id."
              },
              "name": {
                "type": "string"
              },
              "key": {
                "type": "string",
                "description": "The full API key. Shown only now."
              },
              "keyPrefix": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "test",
                  "live"
                ]
              }
            },
            "required": [
              "id",
              "name",
              "key",
              "keyPrefix",
              "type"
            ],
            "description": "Present when `keyName` was sent."
          },
          "webhook": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string"
                  }
                },
                "required": [
                  "url"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "error": {
                    "type": "string"
                  }
                },
                "required": [
                  "error"
                ],
                "title": "Webhook not saved"
              }
            ],
            "description": "Present when `webhookUrl` was sent and the account was found."
          },
          "apiBaseUrl": {
            "type": "string"
          },
          "dashboardUrl": {
            "type": "string"
          }
        },
        "required": [
          "workspace",
          "verification",
          "apiBaseUrl",
          "dashboardUrl"
        ]
      },
      "EnterpriseRequiredError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "enterprise_required",
              "enterprise_inactive"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "enterprise_required, enterprise_inactive",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "enterprise_required",
          "enterprise_inactive"
        ]
      },
      "EnterpriseWorkspaceCompactList": {
        "type": "object",
        "properties": {
          "workspaces": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The workspace's id."
                },
                "name": {
                  "type": "string"
                },
                "creditBalance": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "name",
                "creditBalance"
              ]
            },
            "description": "Every workspace, newest first, unfiltered and unpaged."
          },
          "summary": {
            "$ref": "#/components/schemas/EnterpriseWorkspaceSummary"
          },
          "maxWorkspaces": {
            "type": "integer"
          },
          "workspacesUsed": {
            "type": "integer"
          }
        },
        "required": [
          "workspaces",
          "summary",
          "maxWorkspaces",
          "workspacesUsed"
        ],
        "title": "Workspaces, compact"
      },
      "EnterpriseWorkspaceCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The workspace's id."
          },
          "name": {
            "type": "string",
            "description": "The name, trimmed."
          },
          "slug": {
            "type": "string",
            "description": "The name in lower case, with every run of other characters turned into one hyphen and no hyphen at either end. Empty when the name has no letters or digits."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the workspace was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "createdAt"
        ]
      },
      "EnterpriseWorkspaceCredits": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "integer",
            "description": "0 when the workspace has no balance yet."
          },
          "lifetimeCredits": {
            "type": "integer",
            "description": "Every credit ever added."
          }
        },
        "required": [
          "balance",
          "lifetimeCredits"
        ]
      },
      "EnterpriseWorkspaceDeleted": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "deletedId": {
            "type": "string",
            "description": "The deleted workspace's id."
          }
        },
        "required": [
          "success",
          "deletedId"
        ]
      },
      "EnterpriseWorkspaceDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The workspace's id."
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the workspace was created. ISO 8601, in UTC."
          },
          "verification": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "status": {
                "type": "string",
                "description": "Where the workspace's business verification is. `processing` means the carrier is reviewing it, and `action_required` that the business has to answer a question. Known values: `pending`, `pending_review`, `submitted`, `in_progress`, `processing`, `action_required`, `verified`, `approved`, `rejected`, `archived`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "pending",
                  "pending_review",
                  "submitted",
                  "in_progress",
                  "processing",
                  "action_required",
                  "verified",
                  "approved",
                  "rejected",
                  "archived"
                ]
              },
              "type": {
                "type": "string",
                "description": "What the verification covers. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "toll_free",
                  "international",
                  "both"
                ]
              },
              "tollFreeNumber": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "businessName": {
                "type": "string"
              }
            },
            "required": [
              "status",
              "type",
              "tollFreeNumber",
              "businessName"
            ],
            "description": "`null` when the workspace has no verification."
          },
          "credits": {
            "type": "integer",
            "description": "The workspace's own credit balance."
          },
          "keyCount": {
            "type": "integer",
            "description": "Active API keys in the workspace."
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "createdAt",
          "verification",
          "credits",
          "keyCount"
        ]
      },
      "EnterpriseWorkspaceInvitation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The invitation's id."
          },
          "organizationId": {
            "type": "string",
            "description": "The workspace's id."
          },
          "email": {
            "type": "string",
            "description": "The invitee's address, in lower case."
          },
          "role": {
            "type": "string",
            "description": "The role the invitee gets. Known values: `admin`, `member`, `viewer`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "admin",
              "member",
              "viewer"
            ]
          },
          "invitedBy": {
            "type": "string",
            "description": "The user who sent it."
          },
          "status": {
            "type": "string",
            "description": "Where the invitation is. Known values: `pending`, `accepted`, `declined`, `expired`, `cancelled`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "pending",
              "accepted",
              "declined",
              "expired",
              "cancelled"
            ]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the invitation stops working. ISO 8601, in UTC."
          },
          "acceptedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was accepted. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When it was sent. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "organizationId",
          "email",
          "role",
          "invitedBy",
          "status",
          "expiresAt",
          "acceptedAt",
          "createdAt"
        ]
      },
      "EnterpriseWorkspaceInvitationCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The invitation's id."
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "description": "The role the invitee gets. Known values: `admin`, `member`, `viewer`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "admin",
              "member",
              "viewer"
            ]
          },
          "status": {
            "type": "string",
            "description": "Where the invitation is. Known values: `pending`, `accepted`, `declined`, `expired`, `cancelled`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "pending",
              "accepted",
              "declined",
              "expired",
              "cancelled"
            ]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the invitation stops working. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "email",
          "role",
          "status",
          "expiresAt"
        ]
      },
      "EnterpriseWorkspaceKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The key's id."
          },
          "name": {
            "type": "string"
          },
          "keyPrefix": {
            "type": [
              "string",
              "null"
            ],
            "description": "The start of the key, such as `sk_test_v1_a`."
          },
          "type": {
            "type": "string",
            "description": "Whether the key simulates or sends for real. Known values: `test`, `live`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "test",
              "live"
            ]
          },
          "scopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was last used. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "keyPrefix",
          "type",
          "scopes",
          "lastUsedAt",
          "createdAt"
        ]
      },
      "EnterpriseWorkspaceKeyCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The key's id."
          },
          "name": {
            "type": "string"
          },
          "keyPrefix": {
            "type": [
              "string",
              "null"
            ],
            "description": "The start of the key, such as `sk_test_v1_a`."
          },
          "type": {
            "type": "string",
            "description": "Whether the key simulates or sends for real. Known values: `test`, `live`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "test",
              "live"
            ]
          },
          "scopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was created. ISO 8601, in UTC."
          },
          "key": {
            "type": "string",
            "description": "The full secret key. Store it now: it is never shown again."
          }
        },
        "required": [
          "id",
          "name",
          "keyPrefix",
          "type",
          "scopes",
          "createdAt",
          "key"
        ]
      },
      "EnterpriseWorkspaceKeyRevoked": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "revokedId": {
            "type": "string",
            "description": "The revoked key's id."
          }
        },
        "required": [
          "success",
          "revokedId"
        ]
      },
      "EnterpriseWorkspaceList": {
        "type": "object",
        "properties": {
          "workspaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnterpriseWorkspaceListItem"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PageNumberPagination"
          },
          "summary": {
            "$ref": "#/components/schemas/EnterpriseWorkspaceSummary"
          },
          "maxWorkspaces": {
            "type": "integer",
            "description": "How many workspaces the account may have."
          },
          "workspacesUsed": {
            "type": "integer",
            "description": "How many workspaces the account has."
          }
        },
        "required": [
          "workspaces",
          "pagination",
          "summary",
          "maxWorkspaces",
          "workspacesUsed"
        ],
        "title": "Workspaces, a page"
      },
      "EnterpriseWorkspaceListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The workspace's id."
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "description": "Whether the workspace can send. Known values: `active`, `suspended`, `provision_failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "active",
              "suspended",
              "provision_failed"
            ]
          },
          "suspendedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the workspace was suspended. ISO 8601, in UTC."
          },
          "suspendReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "verificationStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` when the workspace has no verification.",
            "x-sendly-extensible-enum": [
              "pending",
              "pending_review",
              "submitted",
              "in_progress",
              "processing",
              "action_required",
              "verified",
              "approved",
              "rejected",
              "archived"
            ]
          },
          "rejectionReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the verification was rejected."
          },
          "verificationType": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the verification covers. Known values: `toll_free`, `international`, `both`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "toll_free",
              "international",
              "both"
            ]
          },
          "tollFreeNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "The verified toll-free number, in E.164 format."
          },
          "creditBalance": {
            "type": "integer"
          },
          "keyCount": {
            "type": "integer",
            "description": "API keys in the workspace that were not revoked."
          },
          "messages30d": {
            "type": "integer",
            "description": "Messages in the last 30 days."
          },
          "delivered30d": {
            "type": "integer"
          },
          "failed30d": {
            "type": "integer"
          },
          "monthlyMessageQuota": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The monthly message cap, or `null` for none or a cap of 0."
          },
          "messagesThisMonth": {
            "type": "integer"
          },
          "quotaResetAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When `messagesThisMonth` next resets. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the workspace was created. ISO 8601, in UTC."
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnterpriseWorkspaceTag"
            }
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "status",
          "suspendedAt",
          "suspendReason",
          "verificationStatus",
          "rejectionReason",
          "verificationType",
          "tollFreeNumber",
          "creditBalance",
          "keyCount",
          "messages30d",
          "delivered30d",
          "failed30d",
          "monthlyMessageQuota",
          "messagesThisMonth",
          "quotaResetAt",
          "createdAt",
          "tags"
        ]
      },
      "EnterpriseWorkspaceQuota": {
        "type": "object",
        "properties": {
          "monthlyMessageQuota": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The most messages the workspace may send a month. `null` is no limit."
          },
          "messagesThisMonth": {
            "type": "integer",
            "description": "Messages the workspace has sent since the quota last reset."
          },
          "quotaResetAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the monthly count last reset. ISO 8601, in UTC."
          }
        },
        "required": [
          "monthlyMessageQuota",
          "messagesThisMonth",
          "quotaResetAt"
        ]
      },
      "EnterpriseWorkspaceSummary": {
        "type": "object",
        "properties": {
          "totalCredits": {
            "type": "integer",
            "description": "The credit balance of every workspace added up, whatever the filters."
          },
          "pendingVerifications": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The workspace's id."
                },
                "name": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "name"
              ]
            },
            "description": "Up to 10 workspaces whose verification is `pending`, `submitted` or `waiting_for_customer` in its stored form."
          },
          "verificationBreakdown": {
            "type": "object",
            "properties": {
              "verified": {
                "type": "integer"
              },
              "pending": {
                "type": "integer"
              },
              "submitted": {
                "type": "integer",
                "description": "Submitted, in progress, or waiting on the carrier."
              },
              "rejected": {
                "type": "integer"
              },
              "unverified": {
                "type": "integer",
                "description": "No verification, or one in any other state."
              }
            },
            "required": [
              "verified",
              "pending",
              "submitted",
              "rejected",
              "unverified"
            ],
            "description": "Every workspace counted once by its verification status."
          }
        },
        "required": [
          "totalCredits",
          "pendingVerifications",
          "verificationBreakdown"
        ],
        "description": "Totals over every workspace the key's owner owns, before filters and paging."
      },
      "EnterpriseWorkspaceTag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The tag's id."
          },
          "enterpriseAccountId": {
            "type": "string",
            "description": "The enterprise account the tag belongs to."
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": [
              "string",
              "null"
            ],
            "description": "A hex color, such as `#6366f1`."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the tag was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "enterpriseAccountId",
          "name",
          "color",
          "createdAt"
        ]
      },
      "EnterpriseWorkspaceWebhookTestResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the endpoint accepted the test event."
          },
          "message": {
            "type": "string",
            "description": "What happened, as `Test webhook delivered successfully in 120ms` or `Test webhook failed: ...`. On an unexpected failure the sentence carries the internal error text."
          },
          "delivery": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The test delivery's id."
              },
              "delivery_id": {
                "type": "string",
                "description": "Same as `id`."
              },
              "webhook_url": {
                "type": "string"
              },
              "event_type": {
                "type": "string",
                "enum": [
                  "webhook.test"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "delivered",
                  "failed"
                ]
              },
              "response_time": {
                "type": "integer",
                "description": "Milliseconds the endpoint took."
              },
              "status_code": {
                "type": "integer",
                "description": "The endpoint's HTTP status."
              },
              "response_body": {
                "type": "string",
                "description": "The first 500 characters of the endpoint's answer."
              },
              "error": {
                "type": "string",
                "description": "Why the delivery failed."
              },
              "delivered_at": {
                "type": "string",
                "format": "date-time",
                "description": "When the endpoint accepted it. ISO 8601, in UTC."
              }
            },
            "required": [
              "id",
              "delivery_id",
              "webhook_url",
              "event_type",
              "status"
            ],
            "description": "Absent when the test could not be attempted."
          }
        },
        "required": [
          "success",
          "message"
        ]
      },
      "ErrorEnvelope": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "A stable, machine-readable code in snake_case."
          },
          "message": {
            "type": "string",
            "description": "A sentence for people. It can change at any time."
          }
        },
        "required": [
          "error",
          "message"
        ],
        "description": "The error body every new endpoint uses. Extra fields that describe the error sit next to `error` and `message`. Existing endpoints are described exactly as they answer today, which is not always this shape."
      },
      "EventStream": {
        "type": "string",
        "description": "A Server-Sent Events stream that the server never ends. It opens with the comment `: connected`, sends the comment `: keepalive` every 30 seconds, and sends each event as one `data:` line holding a JSON object `{ type, data, timestamp }`, where `timestamp` is milliseconds since the Unix epoch.\n\nEvery 2 seconds the server takes the oldest event, at most one, off the workspace's realtime queue (the user's queue for a key with no workspace). The dashboard reads the same queue, so an event goes to whichever reader takes it first. Events wait in the queue for up to 5 minutes after the last one was added. When the server has no realtime queue configured, the stream carries only the comments.\n\nA key that belongs to a workspace never receives `organization_update`, `incoming_call`, `call_update`, `voice_update` or the `enterprise_*` events, which go only to each user's own queue, nor the `member_update` and `invitation_update` events sent to each member. A key with no workspace never receives `number_update`, `number_message`, `tendlc_update`, `rcs_update` or `hold_update`, which go only to a workspace's queue.\n\nKnown event types: `new_message`, `message_status`, `conversation_update`, `credit_update`, `batch_progress`, `campaign_status`, `webhook_delivery`, `webhook_recovery_progress`, `verification_status`, `port_request_update`, `number_update`, `number_message`, `tendlc_update`, `rcs_update`, `hold_update`, `invitation_update`, `member_update`, `organization_update`, `incoming_call`, `call_update`, `voice_update`, `enterprise_workspace_update`, `enterprise_credit_update`, `enterprise_message_update`, `enterprise_audit_update`, `enterprise_verification_update`. More can be added at any time.",
        "example": ": connected\n\ndata: {\"type\":\"message_status\",\"data\":{\"messageId\":\"00000000-0000-4000-8000-000000000001\",\"status\":\"delivered\"},\"timestamp\":1767225600000}\n\n"
      },
      "FileTooLargeError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "file_too_large"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "description": "Sent by the server's last error handler when the upload middleware refuses a file over the endpoint's size limit, before the handler runs. `message` names the field.",
        "title": "File too large",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "file_too_large"
        ]
      },
      "GenerateBusinessPageRequest": {
        "type": "object",
        "properties": {
          "businessName": {
            "type": "string",
            "minLength": 1,
            "description": "The business's name, shown on the page."
          },
          "useCase": {
            "type": "string"
          },
          "useCaseSummary": {
            "type": "string"
          },
          "contactEmail": {
            "type": "string"
          },
          "contactPhone": {
            "type": "string",
            "description": "A contact phone number. One that is not a valid phone number is left out, and the page is generated without it."
          },
          "contact_phone": {
            "type": "string",
            "description": "Read when `contactPhone` is absent."
          },
          "socialUrl": {
            "type": "string",
            "description": "A website or social profile link. `https://` is added when it has no scheme; one that is still not a valid URL is left out."
          },
          "social_url": {
            "type": "string",
            "description": "Read when `socialUrl` is absent."
          },
          "businessAddress": {
            "type": "string"
          },
          "organizationId": {
            "type": "string",
            "description": "The team workspace the page belongs to, which the key's owner must own. Without it, the page belongs to no workspace."
          }
        },
        "required": [
          "businessName"
        ]
      },
      "GeneratedBusinessPage": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "The page's slug: the business name in lower case with a random 4 character suffix."
          },
          "url": {
            "type": "string",
            "description": "The page's public URL, `https://sendly.live/biz/{slug}`."
          },
          "pageId": {
            "type": "string",
            "description": "The page's id."
          }
        },
        "required": [
          "slug",
          "url",
          "pageId"
        ]
      },
      "GeneratedTemplate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "A suggested name, in snake_case."
          },
          "text": {
            "type": "string",
            "description": "The suggested text, at most 160 characters, with `{{key}}` placeholders."
          },
          "variables": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The variables' names, without the braces."
          },
          "category": {
            "type": "string",
            "description": "The suggested category. Known values: `transactional`, `marketing`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "transactional",
              "marketing"
            ]
          }
        },
        "required": [
          "name",
          "text",
          "variables",
          "category"
        ],
        "description": "A suggested template. Nothing is saved: create it with `POST /api/v1/templates`.",
        "x-sendly-visibility": "preview"
      },
      "GroupMessageSent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "status": {
            "type": "string",
            "enum": [
              "sent"
            ]
          },
          "to": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "phoneNumber": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                }
              },
              "required": [
                "phoneNumber",
                "status"
              ]
            },
            "description": "Each recipient and the carrier's first status for it."
          },
          "group_message_id": {
            "type": "string",
            "description": "The carrier's id for the group."
          }
        },
        "required": [
          "id",
          "status",
          "to",
          "group_message_id"
        ],
        "title": "Group message sent",
        "x-sendly-visibility": "preview"
      },
      "GroupMessageSimulated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "status": {
            "type": "string",
            "enum": [
              "delivered"
            ]
          },
          "to": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The recipients, in E.164 format."
          },
          "simulated": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "to",
          "simulated",
          "message"
        ],
        "description": "A test key, or an account not verified to send to the US and Canada yet.",
        "title": "Group message simulated",
        "x-sendly-visibility": "preview"
      },
      "IdempotencyKeyMismatchError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "idempotency_key_mismatch"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "idempotency_key_mismatch",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "idempotency_key_mismatch"
        ]
      },
      "ImportContactsResult": {
        "type": "object",
        "properties": {
          "imported": {
            "type": "integer",
            "description": "How many contacts were created."
          },
          "skippedDuplicates": {
            "type": "integer",
            "description": "How many rows named a number the workspace already has."
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "The row's position in `contacts`, from 0."
                },
                "phone": {
                  "type": "string",
                  "description": "The row's phone number after spaces, dashes and parentheses were removed. For an empty number, the row's `phone` as sent, or an empty string."
                },
                "error": {
                  "type": "string",
                  "description": "Why the row was skipped. Known values: `Empty phone number`, `Invalid E.164 format`, `Duplicate in import`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "Empty phone number",
                    "Invalid E.164 format",
                    "Duplicate in import"
                  ]
                }
              },
              "required": [
                "index",
                "phone",
                "error"
              ]
            },
            "description": "The first 50 rows that were skipped, and why."
          },
          "totalErrors": {
            "type": "integer",
            "description": "How many rows were skipped."
          }
        },
        "required": [
          "imported",
          "skippedDuplicates",
          "errors",
          "totalErrors"
        ]
      },
      "InsufficientCreditsError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "insufficient_credits"
            ]
          },
          "message": {
            "type": "string"
          },
          "creditsNeeded": {
            "type": "integer"
          },
          "currentBalance": {
            "type": "integer"
          }
        },
        "required": [
          "error",
          "message",
          "creditsNeeded",
          "currentBalance"
        ],
        "title": "insufficient_credits",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "insufficient_credits"
        ]
      },
      "InsufficientPermissionsError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "insufficient_permissions"
            ]
          },
          "message": {
            "type": "string"
          },
          "hint": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "insufficient_permissions",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "insufficient_permissions"
        ]
      },
      "InternalError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "internal_error"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "internal_error",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "internal_error"
        ]
      },
      "InvalidIdempotencyKeyError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_idempotency_key"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "invalid_idempotency_key",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "invalid_idempotency_key"
        ]
      },
      "InvalidRequestError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_request"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "invalid_request",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "invalid_request"
        ]
      },
      "InvalidUploadError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_upload"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "description": "Sent by the server's last error handler when the upload middleware cannot take the multipart body, before the handler runs: a file in a field it does not read, more files or fields than it takes, a field over its size limit, or a body that cannot be read, such as one without a boundary.",
        "title": "Invalid upload",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "invalid_upload"
        ]
      },
      "Label": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The label's id."
          },
          "userId": {
            "type": "string",
            "description": "The id of the user who owns the API key that created the label."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace the label belongs to. `null` for a label of a personal account."
          },
          "name": {
            "type": "string",
            "description": "The label's name, as sent. Unique within the workspace, matched exactly."
          },
          "color": {
            "type": "string",
            "description": "The label's color, as sent, such as `#2563eb`. Defaults to `#6b7280`."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "As sent. `null` when none, or an empty one, was sent."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the label was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "name",
          "color",
          "description",
          "createdAt"
        ],
        "description": "A label for organizing conversations and messages."
      },
      "LabelList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Label"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "LimitHasMorePagination": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "integer",
            "description": "The page size used."
          },
          "has_more": {
            "type": "boolean",
            "description": "`true` when the page is full, so a later page may have items."
          }
        },
        "required": [
          "limit",
          "has_more"
        ],
        "description": "A page size and whether the page was full, with no offset."
      },
      "LimitOffsetPagination": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "integer",
            "description": "The page size used."
          },
          "offset": {
            "type": "integer",
            "description": "How many items were skipped."
          }
        },
        "required": [
          "limit",
          "offset"
        ],
        "description": "The page asked for, with no total: a page shorter than `limit` is the last one."
      },
      "ListedPhoneNumber": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The number's id."
          },
          "phoneNumber": {
            "type": "string",
            "description": "The number, in E.164 format."
          },
          "status": {
            "type": "string",
            "description": "Where the number is in its lifecycle. Only an `active` number can send. A `requirements_required` number with `requirementsSubmittedAt` set is under review; without it, it still needs documents. Released numbers are never listed. Known values: `active`, `provisioning`, `requirements_required`, `failed`, `suspended`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "active",
              "provisioning",
              "requirements_required",
              "failed",
              "suspended"
            ]
          },
          "source": {
            "type": "string",
            "description": "How the workspace got the number: bought here, set up through toll-free verification, hosted for SMS, or ported in. Known values: `purchased`, `provisioned`, `ported_hosted_sms`, `ported_full`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "purchased",
              "provisioned",
              "ported_hosted_sms",
              "ported_full"
            ]
          },
          "countryCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "The ISO 3166-1 alpha-2 country code. `null` on some older numbers that were never stamped with one."
          },
          "phoneNumberType": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` when the number's type was never recorded.",
            "x-sendly-extensible-enum": [
              "local",
              "toll_free",
              "mobile",
              "national"
            ]
          },
          "monthlyCostCents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The monthly price, in US cents. `null` for a number that is not billed monthly, such as a toll-free verified number."
          },
          "requirementsSubmittedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the number's registration details and documents were submitted for review. ISO 8601, in UTC."
          },
          "pendingCancellation": {
            "type": "boolean",
            "description": "`true` when the number is scheduled to be released at the end of the paid month."
          },
          "scheduledReleaseAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When a scheduled release takes effect. ISO 8601, in UTC."
          },
          "voiceEnabled": {
            "type": "boolean",
            "description": "Whether the number can take and place phone calls."
          },
          "voiceMode": {
            "type": "string",
            "description": "How the number answers calls: `none` when voice is off, `ring_dashboard` to ring the team in the dashboard, `agent` for an AI agent. Known values: `none`, `ring_dashboard`, `agent`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "none",
              "ring_dashboard",
              "agent"
            ]
          }
        },
        "required": [
          "id",
          "phoneNumber",
          "status",
          "source",
          "countryCode",
          "phoneNumberType",
          "monthlyCostCents",
          "requirementsSubmittedAt",
          "pendingCancellation",
          "scheduledReleaseAt",
          "voiceEnabled",
          "voiceMode"
        ],
        "description": "A number the workspace owns, as `GET /api/v1/numbers` lists it: no `isDefault`."
      },
      "LiveKeyRequiredError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "live_key_required"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "live_key_required",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "live_key_required"
        ]
      },
      "LiveResendResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The verification's id."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending"
            ]
          },
          "phone": {
            "type": "string",
            "description": "The phone number the code went to."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the new code expires. ISO 8601, in UTC."
          },
          "sandbox": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "message": {
            "type": "string",
            "enum": [
              "OTP resent successfully"
            ]
          }
        },
        "required": [
          "id",
          "status",
          "phone",
          "expires_at",
          "sandbox",
          "message"
        ],
        "title": "New code sent"
      },
      "LiveVerificationResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The verification's id."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending"
            ]
          },
          "phone": {
            "type": "string",
            "description": "The phone number, as sent in `to`."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the code expires. ISO 8601, in UTC."
          },
          "sandbox": {
            "type": "boolean",
            "enum": [
              false
            ]
          }
        },
        "required": [
          "id",
          "status",
          "phone",
          "expires_at",
          "sandbox"
        ],
        "title": "Code sent"
      },
      "MediaFile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The media file's id, starting with `upload_`."
          },
          "url": {
            "type": "string",
            "description": "The public URL of the stored image. Pass it in `mediaUrls` on `POST /api/v1/messages` to send it as an MMS."
          },
          "content_type": {
            "type": "string",
            "enum": [
              "image/jpeg",
              "image/png",
              "image/gif"
            ],
            "description": "The stored image's type, read from the file's bytes."
          },
          "size_bytes": {
            "type": "integer",
            "description": "The stored size in bytes."
          },
          "filename": {
            "type": "string",
            "description": "The file name the upload's multipart part was sent with."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the file was uploaded. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "url",
          "content_type",
          "size_bytes",
          "filename",
          "created_at"
        ],
        "description": "A stored image, as `GET /api/v1/media` lists it."
      },
      "MediaList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MediaFile"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "to": {
            "type": "string",
            "description": "The recipient: a phone number in E.164 format, or a sender label for a simulated inbound message. For a group MMS, every recipient's number, joined by commas."
          },
          "from": {
            "type": "string",
            "description": "The sender: a phone number, short code, alphanumeric sender ID or agent name."
          },
          "text": {
            "type": "string",
            "description": "The message body. Empty for a template or media-only message."
          },
          "status": {
            "type": "string",
            "description": "Where the message is in its lifecycle. `partial` belongs to a group MMS only: every recipient has a final result, some were delivered, and the rest failed or bounced. Known values: `queued`, `sent`, `delivered`, `read`, `failed`, `bounced`, `retrying`, `received`, `partial`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "queued",
              "sent",
              "delivered",
              "read",
              "failed",
              "bounced",
              "retrying",
              "received",
              "partial"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the message failed, in plain English. A sandbox message carries the simulated error as is."
          },
          "errorCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "The error code, such as `E001`."
          },
          "retryCount": {
            "type": "integer",
            "description": "How many times the send has been retried."
          },
          "segments": {
            "type": "integer",
            "description": "How many SMS segments the text needed."
          },
          "creditsUsed": {
            "type": "integer",
            "description": "Credits charged. 0 for a simulated or refunded message."
          },
          "isSandbox": {
            "type": "boolean",
            "description": "Whether the message was simulated."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was created. ISO 8601, in UTC."
          },
          "deliveredAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the message was delivered. ISO 8601, in UTC."
          },
          "message_format": {
            "type": "string",
            "description": "The channel and format the message was sent in. Known values: `sms`, `mms`, `whatsapp`, `rcs`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "sms",
              "mms",
              "whatsapp",
              "rcs"
            ]
          },
          "messageFormat": {
            "type": "string",
            "description": "The channel and format the message was sent in. Known values: `sms`, `mms`, `whatsapp`, `rcs`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "sms",
              "mms",
              "whatsapp",
              "rcs"
            ]
          },
          "batch_id": {
            "type": "string",
            "description": "The batch that sent the message. Present only for a batch message."
          },
          "batchId": {
            "type": "string",
            "description": "Same as `batch_id`."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Present only when the message has media."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Same as `media_urls`."
          },
          "fallback": {
            "type": "object",
            "properties": {
              "channel": {
                "type": "string",
                "enum": [
                  "sms"
                ]
              },
              "status": {
                "type": "string",
                "description": "`pending` until WhatsApp's outcome is known; `sent` when the SMS went; `failed` when the SMS carrier refused it or credits ran out; `unavailable` when the SMS could no longer be sent from this number; `skipped` when the WhatsApp failure isn't one an SMS fixes, such as the recipient opting out. Known values: `pending`, `sent`, `failed`, `unavailable`, `skipped`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "pending",
                  "sent",
                  "failed",
                  "unavailable",
                  "skipped"
                ]
              },
              "reason": {
                "type": "string",
                "description": "What made the message fall back. Known values: `window_closed`, `whatsapp_refused`, `whatsapp_failed`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "window_closed",
                  "whatsapp_refused",
                  "whatsapp_failed"
                ]
              },
              "messageId": {
                "type": "string",
                "description": "The SMS message's id, once it exists."
              },
              "creditsUsed": {
                "type": "integer",
                "description": "Credits charged for the SMS."
              },
              "error": {
                "type": "string",
                "description": "Why the SMS didn't go, in plain English."
              },
              "contentDropped": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Template parts with no SMS form, such as `quick_replies` or `header_media`."
              }
            },
            "required": [
              "channel",
              "status"
            ],
            "description": "The SMS fallback of a WhatsApp message sent with `fallbackToSms: true`."
          },
          "fallbackOf": {
            "type": "string",
            "description": "An SMS fallback: the id of the WhatsApp message it replaced."
          }
        },
        "required": [
          "id",
          "to",
          "from",
          "text",
          "status",
          "direction",
          "error",
          "errorCode",
          "retryCount",
          "segments",
          "creditsUsed",
          "isSandbox",
          "createdAt",
          "deliveredAt",
          "message_format",
          "messageFormat"
        ],
        "description": "A message, as `GET /api/v1/messages` and `GET /api/v1/messages/{id}` return it."
      },
      "MessageBatch": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The batch's id."
          },
          "status": {
            "type": "string",
            "description": "`processing` while sending. Once done, `failed` when every message failed, `partial_failure` when some did, and `completed` otherwise. Known values: `processing`, `completed`, `partial_failure`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "processing",
              "completed",
              "partial_failure",
              "failed"
            ]
          },
          "total": {
            "type": "integer",
            "description": "The messages the batch sends."
          },
          "queued": {
            "type": "integer",
            "description": "Messages not sent yet, as last counted."
          },
          "sent": {
            "type": "integer",
            "description": "Messages the carrier took, as last counted."
          },
          "delivered": {
            "type": "integer",
            "description": "Messages delivered."
          },
          "failed": {
            "type": "integer",
            "description": "Messages failed, bounced or undelivered."
          },
          "creditsReserved": {
            "type": "integer",
            "description": "Credits charged up front."
          },
          "creditsUsed": {
            "type": "integer",
            "description": "Credits the batch's messages cost."
          },
          "creditsRefunded": {
            "type": "integer",
            "description": "`creditsReserved` less `creditsUsed`."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the batch was created. ISO 8601, in UTC."
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the batch finished sending. ISO 8601, in UTC."
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The message's id."
                },
                "to": {
                  "type": "string",
                  "description": "The recipient, in E.164 format."
                },
                "status": {
                  "type": "string",
                  "description": "Where the message is in its lifecycle. `partial` belongs to a group MMS only: every recipient has a final result, some were delivered, and the rest failed or bounced. Known values: `queued`, `sent`, `delivered`, `read`, `failed`, `bounced`, `retrying`, `received`, `partial`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "queued",
                    "sent",
                    "delivered",
                    "read",
                    "failed",
                    "bounced",
                    "retrying",
                    "received",
                    "partial"
                  ]
                },
                "error": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Why the message failed."
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the message was created. ISO 8601, in UTC."
                },
                "deliveredAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "description": "When the message was delivered. ISO 8601, in UTC."
                }
              },
              "required": [
                "id",
                "to",
                "status",
                "error",
                "createdAt",
                "deliveredAt"
              ]
            },
            "description": "Every message of the batch, oldest first."
          }
        },
        "required": [
          "id",
          "status",
          "total",
          "queued",
          "sent",
          "delivered",
          "failed",
          "creditsReserved",
          "creditsUsed",
          "creditsRefunded",
          "createdAt",
          "completedAt",
          "messages"
        ]
      },
      "MessageBatchAccepted": {
        "type": "object",
        "properties": {
          "batchId": {
            "type": "string",
            "description": "The batch's id, `batch_` and 32 hex characters."
          },
          "status": {
            "type": "string",
            "enum": [
              "processing"
            ]
          },
          "total": {
            "type": "integer",
            "description": "The recipients that will be sent to, without the skipped ones."
          },
          "sent": {
            "type": "integer",
            "description": "Always 0."
          },
          "failed": {
            "type": "integer",
            "description": "Always 0."
          },
          "optedOutSkipped": {
            "type": "integer",
            "description": "Recipients skipped because they opted out."
          },
          "invalidSkipped": {
            "type": "integer",
            "description": "Recipients skipped because their number cannot receive texts."
          },
          "creditsUsed": {
            "type": "integer",
            "description": "Always 0."
          },
          "creditsRefunded": {
            "type": "integer",
            "description": "Always 0."
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "The message's position among the recipients that were sent to."
                },
                "id": {
                  "type": "string",
                  "description": "The message's id. Empty when the message could not be created."
                },
                "to": {
                  "type": "string",
                  "description": "The recipient, in E.164 format."
                },
                "status": {
                  "type": "string",
                  "description": "What happened to the send. Known values: `sent`, `failed`, `retrying`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "sent",
                    "failed",
                    "retrying"
                  ]
                },
                "error": {
                  "type": "string",
                  "description": "Why the send failed."
                }
              },
              "required": [
                "index",
                "id",
                "to",
                "status"
              ]
            },
            "description": "Always empty."
          }
        },
        "required": [
          "batchId",
          "status",
          "total",
          "sent",
          "failed",
          "optedOutSkipped",
          "invalidSkipped",
          "creditsUsed",
          "creditsRefunded",
          "messages"
        ],
        "description": "The batch was accepted and is being sent in the background. Read it with `GET /api/v1/messages/batch/{id}`.",
        "title": "Batch accepted"
      },
      "MessageBatchCompleted": {
        "type": "object",
        "properties": {
          "batchId": {
            "type": "string",
            "description": "The batch's id, `batch_` and 32 hex characters."
          },
          "status": {
            "type": "string",
            "description": "How the batch ended: `failed` when every message failed, `partial_failure` when some did, and `completed` otherwise. Known values: `completed`, `partial_failure`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "completed",
              "partial_failure",
              "failed"
            ]
          },
          "total": {
            "type": "integer",
            "description": "Every recipient in the request, including the skipped ones."
          },
          "sent": {
            "type": "integer"
          },
          "failed": {
            "type": "integer"
          },
          "retrying": {
            "type": "integer",
            "description": "Always 0: a test key's sends are never retried."
          },
          "optedOutSkipped": {
            "type": "integer",
            "description": "Recipients skipped because they opted out."
          },
          "invalidSkipped": {
            "type": "integer",
            "description": "Recipients skipped because their number cannot receive texts."
          },
          "creditsUsed": {
            "type": "integer"
          },
          "creditsRefunded": {
            "type": "integer"
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "The message's position among the recipients that were sent to."
                },
                "id": {
                  "type": "string",
                  "description": "The message's id. Empty when the message could not be created."
                },
                "to": {
                  "type": "string",
                  "description": "The recipient, in E.164 format."
                },
                "status": {
                  "type": "string",
                  "description": "What happened to the send. Known values: `sent`, `failed`, `retrying`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "sent",
                    "failed",
                    "retrying"
                  ]
                },
                "error": {
                  "type": "string",
                  "description": "Why the send failed."
                }
              },
              "required": [
                "index",
                "id",
                "to",
                "status"
              ]
            }
          }
        },
        "required": [
          "batchId",
          "status",
          "total",
          "sent",
          "failed",
          "retrying",
          "optedOutSkipped",
          "invalidSkipped",
          "creditsUsed",
          "creditsRefunded",
          "messages"
        ],
        "description": "A test key's batch, sent before the answer. Every message is simulated: `sent`, or `failed` for a failure sandbox number.",
        "title": "Batch sent"
      },
      "MessageBatchList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MessageBatchSummary"
            }
          },
          "count": {
            "type": "integer",
            "description": "How many items are in this response."
          }
        },
        "required": [
          "data",
          "count"
        ]
      },
      "MessageBatchPreview": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "Every recipient sent, duplicates included."
          },
          "sendable": {
            "type": "integer"
          },
          "blocked": {
            "type": "integer"
          },
          "duplicates": {
            "type": "integer",
            "description": "Recipients repeated by digits, which are dropped."
          },
          "creditsNeeded": {
            "type": "integer",
            "description": "What the sendable messages would cost."
          },
          "creditBalance": {
            "type": "integer",
            "description": "The balance, or the pool's balance."
          },
          "hasSufficientCredits": {
            "type": "boolean"
          },
          "pooled": {
            "type": "boolean",
            "description": "Whether the balance is an enterprise pool."
          },
          "keyType": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ]
          },
          "keyScopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "hasWriteScope": {
            "type": "boolean",
            "description": "Whether the key has `sms:send`."
          },
          "messagingProfile": {
            "type": "object",
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "canSendDomestic": {
                "type": "boolean"
              },
              "canSendInternational": {
                "type": "boolean"
              },
              "verificationStatus": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "verificationType": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "canSendDomestic",
              "canSendInternational",
              "verificationStatus",
              "verificationType"
            ]
          },
          "byCountry": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "count": {
                  "type": "integer"
                },
                "credits": {
                  "type": "integer"
                },
                "tier": {
                  "type": "string"
                },
                "allowed": {
                  "type": "boolean"
                },
                "blockedReason": {
                  "type": "string"
                }
              },
              "required": [
                "count",
                "credits",
                "tier",
                "allowed"
              ]
            },
            "description": "Recipients by country code."
          },
          "blockedMessages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "to": {
                  "type": "string"
                },
                "reason": {
                  "type": "string"
                }
              },
              "required": [
                "index",
                "to",
                "reason"
              ]
            }
          },
          "compliance": {
            "type": "object",
            "properties": {
              "messageType": {
                "type": "string",
                "description": "The `messageType` as sent, or `marketing` when none was."
              },
              "optedOutBlocked": {
                "type": "integer"
              },
              "shaftBlocked": {
                "type": "integer"
              },
              "quietHoursBlocked": {
                "type": "integer",
                "description": "Always 0: quiet hours reschedule."
              },
              "quietHoursRescheduled": {
                "type": "integer"
              },
              "shaftBlockedMessages": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer"
                    },
                    "to": {
                      "type": "string"
                    },
                    "category": {
                      "type": "string"
                    },
                    "matchedTerms": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "index",
                    "to",
                    "category",
                    "matchedTerms"
                  ]
                }
              },
              "quietHoursBlockedMessages": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer"
                    },
                    "to": {
                      "type": "string"
                    },
                    "recipientTimezone": {
                      "type": "string"
                    },
                    "recipientLocalTime": {
                      "type": "string"
                    },
                    "nextAllowedTime": {
                      "type": "string",
                      "format": "date-time",
                      "description": "The earliest time a marketing message may go. ISO 8601, in UTC."
                    }
                  },
                  "required": [
                    "index",
                    "to",
                    "recipientTimezone",
                    "recipientLocalTime"
                  ]
                }
              }
            },
            "required": [
              "messageType",
              "optedOutBlocked",
              "shaftBlocked",
              "quietHoursBlocked",
              "quietHoursRescheduled",
              "shaftBlockedMessages",
              "quietHoursBlockedMessages"
            ]
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "total",
          "sendable",
          "blocked",
          "duplicates",
          "creditsNeeded",
          "creditBalance",
          "hasSufficientCredits",
          "pooled",
          "keyType",
          "keyScopes",
          "hasWriteScope",
          "messagingProfile",
          "byCountry",
          "blockedMessages",
          "compliance",
          "warnings"
        ]
      },
      "MessageBatchSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The batch's id."
          },
          "status": {
            "type": "string",
            "description": "`processing` while sending. Once done, `failed` when every message failed, `partial_failure` when some did, and `completed` otherwise. Known values: `processing`, `completed`, `partial_failure`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "processing",
              "completed",
              "partial_failure",
              "failed"
            ]
          },
          "total": {
            "type": "integer",
            "description": "The messages the batch sends."
          },
          "queued": {
            "type": "integer",
            "description": "Messages not sent yet, as last counted."
          },
          "sent": {
            "type": "integer",
            "description": "Messages the carrier took, as last counted."
          },
          "delivered": {
            "type": "integer",
            "description": "Messages delivered."
          },
          "failed": {
            "type": "integer",
            "description": "Messages failed, bounced or undelivered."
          },
          "creditsReserved": {
            "type": "integer",
            "description": "Credits charged up front."
          },
          "creditsUsed": {
            "type": "integer",
            "description": "Credits the batch's messages cost."
          },
          "creditsRefunded": {
            "type": "integer",
            "description": "`creditsReserved` less `creditsUsed`."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the batch was created. ISO 8601, in UTC."
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the batch finished sending. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "status",
          "total",
          "queued",
          "sent",
          "delivered",
          "failed",
          "creditsReserved",
          "creditsUsed",
          "creditsRefunded",
          "createdAt",
          "completedAt"
        ],
        "description": "A batch, as `GET /api/v1/messages/batches` lists it."
      },
      "MessageDraft": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The draft's id."
          },
          "userId": {
            "type": "string",
            "description": "The id of the account that owns the draft."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace the draft belongs to. `null` for a personal account."
          },
          "conversationId": {
            "type": "string",
            "description": "The conversation the draft replies to."
          },
          "text": {
            "type": "string",
            "description": "The reply to send. An edit can leave it empty, which approval then refuses unless the draft has media."
          },
          "mediaUrls": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "object",
                "additionalProperties": {}
              },
              {
                "type": "null"
              }
            ],
            "description": "Media URLs to send with the reply. `[]` when none were given. Stored as sent: the server checks nothing, so a draft created or edited as documented holds the value described, but `POST` keeps any value but `\"\"`, `0`, `false` and `null`, and `PATCH` any value at all, so this can also be a string, a number, a boolean, an array, an object, or `null` after an edit set it to `null`."
          },
          "metadata": {
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": {}
              },
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "object",
                "additionalProperties": {}
              },
              {
                "type": "null"
              }
            ],
            "description": "Your own JSON object. `{}` when none was given. Approval passes it to the message only when it is an object. Stored as sent: the server checks nothing, so a draft created or edited as documented holds the value described, but `POST` keeps any value but `\"\"`, `0`, `false` and `null`, and `PATCH` any value at all, so this can also be a string, a number, a boolean, an array, an object, or `null` after an edit set it to `null`."
          },
          "status": {
            "type": "string",
            "description": "Where the draft is in review. Only a `pending` draft can be edited, approved or rejected. Known values: `pending`, `approved`, `rejected`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "pending",
              "approved",
              "rejected"
            ]
          },
          "source": {
            "type": "string",
            "description": "Who wrote the draft, as given when it was created. Defaults to `ai`."
          },
          "createdBy": {
            "type": "string",
            "description": "The id of the API key that created the draft, or of the user for a draft made in the dashboard."
          },
          "reviewedBy": {
            "type": [
              "string",
              "null"
            ],
            "description": "The id of the account that approved or rejected the draft."
          },
          "reviewedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the draft was approved or rejected. ISO 8601, in UTC."
          },
          "rejectionReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "The reason given when the draft was rejected."
          },
          "messageId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The message an API approval sent. `null` until then, and for a draft approved in the dashboard, which sends nothing."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the draft was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the draft last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "conversationId",
          "text",
          "mediaUrls",
          "metadata",
          "status",
          "source",
          "createdBy",
          "reviewedBy",
          "reviewedAt",
          "rejectionReason",
          "messageId",
          "createdAt",
          "updatedAt"
        ],
        "description": "A reply waiting for a person to review it before it is sent."
      },
      "MessageDraftList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MessageDraft"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/TotalPagination"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "MessageLabelsAdded": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "success"
        ]
      },
      "MessageList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Message"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/OffsetPagination"
          },
          "count": {
            "type": "integer",
            "description": "How many messages are on this page. Deprecated: use `data.length`.",
            "deprecated": true
          }
        },
        "required": [
          "data",
          "pagination",
          "count"
        ]
      },
      "NotFoundError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "not_found"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "not_found",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "not_found"
        ]
      },
      "NumberBuyAction": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "The hosted page to send the person to."
          },
          "code": {
            "type": "string",
            "description": "The short code the person enters on the hosted page. Show it to them."
          },
          "actionCode": {
            "type": "string",
            "description": "The step's identifier, 32 hex characters. Pass it back as `actionCode` once the step is done."
          },
          "expiresAt": {
            "type": "integer",
            "description": "When the step expires, in epoch milliseconds."
          }
        },
        "required": [
          "url",
          "code",
          "actionCode",
          "expiresAt"
        ]
      },
      "NumberCountry": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "The ISO 3166-1 alpha-2 country code."
          },
          "name": {
            "type": "string",
            "description": "The country's name."
          },
          "numberTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "The number type, as the carrier names it. Known values: `local`, `toll_free`, `mobile`, `national`. More can be added at any time, so treat an unknown value as valid.",
              "x-sendly-extensible-enum": [
                "local",
                "toll_free",
                "mobile",
                "national"
              ]
            },
            "description": "The number types that can be bought there. Only `local` for the US and Canada."
          }
        },
        "required": [
          "code",
          "name",
          "numberTypes"
        ]
      },
      "NumberCountryList": {
        "type": "object",
        "properties": {
          "countries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NumberCountry"
            }
          }
        },
        "required": [
          "countries"
        ]
      },
      "NumberOrderingRequirement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The requirement's id."
          },
          "name": {
            "type": "string"
          },
          "fieldType": {
            "type": "string",
            "description": "What the requirement asks for. Known values: `textual`, `address`, `document`, `action`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "textual",
              "address",
              "document",
              "action"
            ]
          },
          "description": {
            "type": "string",
            "description": "Empty when the carrier gives none."
          },
          "example": {
            "type": "string",
            "description": "Empty when the carrier gives none."
          }
        },
        "required": [
          "id",
          "name",
          "fieldType",
          "description",
          "example"
        ]
      },
      "NumberReleaseScheduled": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "scheduled": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "scheduledReleaseAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the number will be released: the last second of the current month. ISO 8601, in UTC."
          }
        },
        "required": [
          "success",
          "scheduled",
          "scheduledReleaseAt"
        ],
        "title": "Release scheduled"
      },
      "NumberReleaseServerError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "sendlyCode": {
            "type": "string",
            "enum": [
              "internal_error"
            ],
            "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
          }
        },
        "required": [
          "error"
        ],
        "description": "`error` holds the internal error's own text, or `Failed to release number`, and there is no `message`.",
        "title": "Release failed",
        "x-sendly-error-shape": "sentence",
        "x-sendly-error-codes": [],
        "x-sendly-proposed-codes": [
          "internal_error"
        ]
      },
      "NumberReleased": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "success"
        ],
        "title": "Released"
      },
      "OffsetHasMorePagination": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "How many items match, across every page."
          },
          "limit": {
            "type": "integer",
            "description": "The page size used."
          },
          "offset": {
            "type": "integer",
            "description": "How many items were skipped."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether a later page has items."
          }
        },
        "required": [
          "total",
          "limit",
          "offset",
          "hasMore"
        ],
        "description": "Offset pagination without page numbers. Ask for the next page with `offset`."
      },
      "OffsetPagination": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "How many items match, across every page."
          },
          "limit": {
            "type": "integer",
            "description": "The page size used."
          },
          "offset": {
            "type": "integer",
            "description": "How many items were skipped."
          },
          "page": {
            "type": "integer",
            "description": "The page number, starting at 1."
          },
          "totalPages": {
            "type": "integer",
            "description": "How many pages there are at this page size."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether a later page has items."
          }
        },
        "required": [
          "total",
          "limit",
          "offset",
          "page",
          "totalPages",
          "hasMore"
        ],
        "description": "Offset pagination. Ask for the next page with `page`, or with `offset` plus `limit`."
      },
      "OrganizationContextError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "Failed to resolve organization context"
            ]
          },
          "sendlyCode": {
            "type": "string",
            "enum": [
              "internal_error"
            ],
            "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
          }
        },
        "required": [
          "error"
        ],
        "description": "`error` holds a sentence, and there is no `message`.",
        "title": "Workspace lookup failed",
        "x-sendly-error-shape": "sentence",
        "x-sendly-error-codes": [],
        "x-sendly-proposed-codes": [
          "internal_error"
        ]
      },
      "OrganizationMembershipError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "Not a member of this organization",
              "Your access to this organization has been suspended"
            ]
          },
          "sendlyCode": {
            "type": "string",
            "enum": [
              "not_workspace_member",
              "workspace_access_suspended"
            ],
            "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
          }
        },
        "required": [
          "error"
        ],
        "description": "`error` holds a sentence, and there is no `message`.",
        "title": "Not a workspace member",
        "x-sendly-error-shape": "sentence",
        "x-sendly-error-codes": [],
        "x-sendly-proposed-codes": [
          "not_workspace_member",
          "workspace_access_suspended"
        ]
      },
      "PageNumberPagination": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "How many items match, across every page."
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The page size used. `null` when `limit` was not a number, which also leaves the list empty."
          },
          "page": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The page number, starting at 1. `null` when `page` was not a number, which also leaves the list empty."
          },
          "totalPages": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How many pages there are at this page size. `null` when `limit` was 0 or not a number."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether a later page has items."
          }
        },
        "required": [
          "total",
          "limit",
          "page",
          "totalPages",
          "hasMore"
        ],
        "description": "Page-number pagination with no offset. Ask for the next page with `page`."
      },
      "PendingWorkspaceUpgrade": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The pending verification's id."
          },
          "businessName": {
            "type": "string",
            "description": "The new entity's legal name."
          },
          "status": {
            "type": "string",
            "description": "Where the upgrade is: `provisioning` while the new number is set up, `pending`, `processing` or `in_progress` while the carrier reviews it, `action_required` when it needs changes from you, and `rejected` when the carrier refused it or a resubmit failed. `pending_review`, `submitted` and `approved` appear when another verification flow on the same workspace writes the status. Known values: `provisioning`, `pending`, `pending_review`, `submitted`, `approved`, `in_progress`, `processing`, `action_required`, `verified`, `rejected`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "provisioning",
              "pending",
              "pending_review",
              "submitted",
              "approved",
              "in_progress",
              "processing",
              "action_required",
              "verified",
              "rejected"
            ]
          },
          "entityType": {
            "type": [
              "string",
              "null"
            ],
            "description": "The new entity's legal form."
          },
          "brnType": {
            "type": [
              "string",
              "null"
            ],
            "description": "What kind of number the BRN is."
          },
          "brnCountry": {
            "type": [
              "string",
              "null"
            ],
            "description": "The country that issued the BRN."
          },
          "tollFreeNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "The new toll-free number, in E.164 format, once one has been reserved."
          },
          "rejectionReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the upgrade was rejected or needs changes."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the upgrade was started. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the upgrade last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "businessName",
          "status",
          "entityType",
          "brnType",
          "brnCountry",
          "tollFreeNumber",
          "rejectionReason",
          "createdAt",
          "updatedAt"
        ]
      },
      "PhoneNumber": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The number's id."
          },
          "phoneNumber": {
            "type": "string",
            "description": "The number, in E.164 format."
          },
          "status": {
            "type": "string",
            "description": "Where the number is in its lifecycle. Only an `active` number can send. A `requirements_required` number with `requirementsSubmittedAt` set is under review; without it, it still needs documents. Released numbers are never listed. Known values: `active`, `provisioning`, `requirements_required`, `failed`, `suspended`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "active",
              "provisioning",
              "requirements_required",
              "failed",
              "suspended"
            ]
          },
          "source": {
            "type": "string",
            "description": "How the workspace got the number: bought here, set up through toll-free verification, hosted for SMS, or ported in. Known values: `purchased`, `provisioned`, `ported_hosted_sms`, `ported_full`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "purchased",
              "provisioned",
              "ported_hosted_sms",
              "ported_full"
            ]
          },
          "countryCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "The ISO 3166-1 alpha-2 country code. `null` on some older numbers that were never stamped with one."
          },
          "phoneNumberType": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` when the number's type was never recorded.",
            "x-sendly-extensible-enum": [
              "local",
              "toll_free",
              "mobile",
              "national"
            ]
          },
          "monthlyCostCents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The monthly price, in US cents. `null` for a number that is not billed monthly, such as a toll-free verified number."
          },
          "requirementsSubmittedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the number's registration details and documents were submitted for review. ISO 8601, in UTC."
          },
          "pendingCancellation": {
            "type": "boolean",
            "description": "`true` when the number is scheduled to be released at the end of the paid month."
          },
          "scheduledReleaseAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When a scheduled release takes effect. ISO 8601, in UTC."
          },
          "isDefault": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether this is the workspace's default sender. `null` on a number stored without the flag."
          },
          "voiceEnabled": {
            "type": "boolean",
            "description": "Whether the number can take and place phone calls."
          },
          "voiceMode": {
            "type": "string",
            "description": "How the number answers calls: `none` when voice is off, `ring_dashboard` to ring the team in the dashboard, `agent` for an AI agent. Known values: `none`, `ring_dashboard`, `agent`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "none",
              "ring_dashboard",
              "agent"
            ]
          }
        },
        "required": [
          "id",
          "phoneNumber",
          "status",
          "source",
          "countryCode",
          "phoneNumberType",
          "monthlyCostCents",
          "requirementsSubmittedAt",
          "pendingCancellation",
          "scheduledReleaseAt",
          "isDefault",
          "voiceEnabled",
          "voiceMode"
        ],
        "description": "A number the workspace owns, as `GET /api/v1/numbers/{id}` returns it."
      },
      "PhoneNumberList": {
        "type": "object",
        "properties": {
          "numbers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ListedPhoneNumber"
            }
          }
        },
        "required": [
          "numbers"
        ]
      },
      "PortCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The new port request's id."
          },
          "status": {
            "type": "string",
            "description": "The carrier order's status when it was created, normally `draft`. Known values are those of `PortRequest.status`.",
            "x-sendly-extensible-enum": [
              "draft",
              "pending",
              "submitted",
              "in-process",
              "exception",
              "foc-date-confirmed",
              "ownership_successful",
              "loa_file_successful",
              "in_review",
              "internal_transfer_pending",
              "rejected",
              "successful",
              "ported",
              "failed",
              "carrier_rejected",
              "ineligible_carrier",
              "cancelled",
              "deleted"
            ]
          },
          "portType": {
            "type": "string",
            "enum": [
              "full_port"
            ]
          }
        },
        "required": [
          "id",
          "status",
          "portType"
        ]
      },
      "PortList": {
        "type": "object",
        "properties": {
          "ports": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PortRequest"
            }
          }
        },
        "required": [
          "ports"
        ]
      },
      "PortRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The port request's id."
          },
          "phoneNumber": {
            "type": "string",
            "description": "The number being ported, in E.164 format."
          },
          "portType": {
            "type": "string",
            "description": "`full_port` moves the number itself; `hosted_sms` brings only its messaging. This API creates `full_port` requests only. Known values: `full_port`, `hosted_sms`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "full_port",
              "hosted_sms"
            ]
          },
          "status": {
            "type": "string",
            "description": "Where the port is. A port in `successful`, `ported`, `failed`, `carrier_rejected`, `ineligible_carrier`, `cancelled` or `deleted` is final; `rejected` is not on that list, so cancel and submit do not refuse it as final. Other values come from the carrier's porting order as it reports them. Known values: `draft`, `pending`, `submitted`, `in-process`, `exception`, `foc-date-confirmed`, `ownership_successful`, `loa_file_successful`, `in_review`, `internal_transfer_pending`, `rejected`, `successful`, `ported`, `failed`, `carrier_rejected`, `ineligible_carrier`, `cancelled`, `deleted`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "pending",
              "submitted",
              "in-process",
              "exception",
              "foc-date-confirmed",
              "ownership_successful",
              "loa_file_successful",
              "in_review",
              "internal_transfer_pending",
              "rejected",
              "successful",
              "ported",
              "failed",
              "carrier_rejected",
              "ineligible_carrier",
              "cancelled",
              "deleted"
            ]
          },
          "statusDetail": {
            "type": [
              "string",
              "null"
            ],
            "description": "More about the status, such as why the port is held."
          },
          "focRequested": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The cutover (FOC) date asked for. ISO 8601, in UTC."
          },
          "focActual": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The cutover (FOC) date the losing carrier confirmed. ISO 8601, in UTC."
          },
          "loaSigned": {
            "type": "boolean",
            "description": "Whether the letter of authorization has been signed."
          },
          "documentsUploaded": {
            "type": "boolean",
            "description": "Whether the porting documents have been uploaded."
          },
          "verificationSubmitted": {
            "type": "boolean",
            "description": "Whether the verification codes have been submitted."
          },
          "submittedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the port was submitted to the losing carrier. ISO 8601, in UTC."
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the port completed. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the port request was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "phoneNumber",
          "portType",
          "status",
          "statusDetail",
          "focRequested",
          "focActual",
          "loaSigned",
          "documentsUploaded",
          "verificationSubmitted",
          "submittedAt",
          "completedAt",
          "createdAt"
        ],
        "description": "A port request, as `GET /api/v1/port` and `GET /api/v1/port/{id}` return it. Carrier ids and carrier names are left out."
      },
      "PortResponse": {
        "type": "object",
        "properties": {
          "port": {
            "$ref": "#/components/schemas/PortRequest"
          }
        },
        "required": [
          "port"
        ]
      },
      "PortabilityResult": {
        "type": "object",
        "properties": {
          "phone_number": {
            "type": "string",
            "description": "The number, as the carrier returned it."
          },
          "portable": {
            "type": "boolean"
          },
          "carrier_name": {
            "type": "string",
            "description": "The number's current carrier. Empty when the carrier did not say."
          },
          "phone_number_type": {
            "type": "string",
            "description": "The kind of number, or an empty string when the carrier did not say. Known values: `local`, `toll_free`, ``. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "local",
              "toll_free",
              ""
            ]
          },
          "fast_portable": {
            "type": "boolean"
          },
          "messaging_capable": {
            "type": "boolean"
          },
          "not_portable_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the number cannot be ported, when it cannot."
          }
        },
        "required": [
          "phone_number",
          "portable",
          "carrier_name",
          "phone_number_type",
          "fast_portable",
          "messaging_capable",
          "not_portable_reason"
        ]
      },
      "PortabilityResults": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PortabilityResult"
            }
          }
        },
        "required": [
          "results"
        ]
      },
      "PreflightCandidate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Echoed back as `verificationId`. Nothing is looked up by it."
          },
          "businessName": {
            "type": "string",
            "description": "The legal business name. Required for a submission."
          },
          "doingBusinessAs": {
            "type": "string",
            "description": "The brand name, when it differs from the legal name."
          },
          "entityType": {
            "type": "string",
            "description": "`SOLE_PROPRIETOR`, `PRIVATE_PROFIT`, `PUBLIC_PROFIT`, `NON_PROFIT` or `GOVERNMENT`. Any other value is reported as an issue."
          },
          "brn": {
            "type": "string",
            "description": "The registration number: an EIN or SSN for the US, a 9-digit Business Number for Canada."
          },
          "brnType": {
            "type": "string",
            "description": "The kind of registration number, such as `EIN`, `SSN` or `BN`."
          },
          "brnCountry": {
            "type": "string",
            "description": "The registration country, two capital letters. `US` and `CA` pick that country's checks. For any other value `addressCountry` decides, and the country is `OTHER` when it is neither `US` nor `CA`."
          },
          "website": {
            "type": "string",
            "description": "The business website, with its scheme. Required. Its domain's registration date is looked up."
          },
          "address1": {
            "type": "string",
            "description": "Address line 1. Required."
          },
          "address2": {
            "type": "string",
            "description": "Address line 2."
          },
          "city": {
            "type": "string",
            "description": "City. Required."
          },
          "state": {
            "type": "string",
            "description": "The state or province by its full name, such as `Texas`. Required. A 2-letter code is reported as an issue."
          },
          "zip": {
            "type": "string",
            "description": "ZIP or postal code. Required."
          },
          "addressCountry": {
            "type": "string",
            "description": "The address's country, read when `brnCountry` is neither `US` nor `CA`."
          },
          "contactFirstName": {
            "type": "string",
            "description": "Contact first name. Required."
          },
          "contactLastName": {
            "type": "string",
            "description": "Contact last name. Required."
          },
          "contactEmail": {
            "type": "string",
            "description": "Contact email. Required."
          },
          "contactPhone": {
            "type": "string",
            "description": "Contact phone, in E.164 format. Required."
          },
          "monthlyVolume": {
            "type": "string",
            "description": "Monthly message volume: `10`, `100`, `1,000`, `10,000`, `100,000`, `250,000`, `500,000`, `750,000`, `1,000,000`, `5,000,000` or `10,000,000+`. Required."
          },
          "useCase": {
            "type": "string",
            "description": "The use case, from the accepted list, such as `Appointments`. Required."
          },
          "useCaseSummary": {
            "type": "string",
            "description": "What the messages are for. Required."
          },
          "sampleMessages": {
            "type": "string",
            "description": "Example messages, which should name the business and say how to opt out. Required."
          },
          "optInWorkflow": {
            "type": "string",
            "description": "How recipients opt in. Required."
          },
          "optInSource": {
            "type": "string",
            "description": "`manual` for an uploaded opt-in screenshot, which adds a warning."
          },
          "additionalInformation": {
            "type": "string",
            "description": "Anything else the reviewer should know. Required."
          },
          "isvReseller": {
            "type": "string",
            "description": "The reseller the messages go through."
          },
          "privacyUrl": {
            "type": "string",
            "description": "The privacy policy URL. Checked for whether it loads."
          },
          "termsUrl": {
            "type": "string",
            "description": "The terms and conditions URL. Checked for whether it loads."
          }
        },
        "description": "The business details a business upgrade would submit, all optional: a missing required field is reported as an issue, not refused. Values are expected to be strings; another type can make the check fail with a 500."
      },
      "PreflightIssue": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "blocker",
              "warning",
              "info"
            ],
            "description": "`blocker`: the submission would be rejected. `warning`: it may be flagged. `info`: a check could not run."
          },
          "field": {
            "type": "string",
            "description": "The submission field the issue is about, by its name in the carrier's review form; `sampleMessages` and `optInImageUrls` by the candidate's name, and `_website` and `_registry` for the website's domain and the business registration. Known values: `businessName`, `corporateWebsite`, `businessAddr1`, `businessAddr2`, `businessCity`, `businessState`, `businessZip`, `businessContactFirstName`, `businessContactLastName`, `businessContactEmail`, `businessContactPhone`, `messageVolume`, `useCase`, `useCaseSummary`, `productionMessageContent`, `optInWorkflow`, `additionalInformation`, `isvReseller`, `businessRegistrationNumber`, `businessRegistrationType`, `businessRegistrationCountry`, `doingBusinessAs`, `entityType`, `privacyPolicyURL`, `termsAndConditionURL`, `sampleMessages`, `optInImageUrls`, `_website`, `_registry`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "businessName",
              "corporateWebsite",
              "businessAddr1",
              "businessAddr2",
              "businessCity",
              "businessState",
              "businessZip",
              "businessContactFirstName",
              "businessContactLastName",
              "businessContactEmail",
              "businessContactPhone",
              "messageVolume",
              "useCase",
              "useCaseSummary",
              "productionMessageContent",
              "optInWorkflow",
              "additionalInformation",
              "isvReseller",
              "businessRegistrationNumber",
              "businessRegistrationType",
              "businessRegistrationCountry",
              "doingBusinessAs",
              "entityType",
              "privacyPolicyURL",
              "termsAndConditionURL",
              "sampleMessages",
              "optInImageUrls",
              "_website",
              "_registry"
            ]
          },
          "code": {
            "type": "string",
            "description": "What is wrong, for code to branch on. Known values: `field_required`, `field_too_long`, `field_pattern_mismatch`, `field_not_in_enum`, `state_unrecognized`, `state_must_be_full_name`, `phone_not_e164`, `phone_missing_plus`, `manual_opt_in_check_ctia`, `samples_missing_stop`, `samples_no_business_attribution`, `sole_prop_no_brn`, `ein_format_invalid`, `ssn_format_invalid`, `sole_prop_with_brn_will_be_cleared`, `brn_format_invalid`, `brn_has_suffix`, `url_unreachable`, `domain_lt_6_months`, `registry_name_mismatch`, `entity_type_mismatch`, `registry_inactive`, `registry_lt_6_months`, `registry_no_match`, `registry_unavailable`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "field_required",
              "field_too_long",
              "field_pattern_mismatch",
              "field_not_in_enum",
              "state_unrecognized",
              "state_must_be_full_name",
              "phone_not_e164",
              "phone_missing_plus",
              "manual_opt_in_check_ctia",
              "samples_missing_stop",
              "samples_no_business_attribution",
              "sole_prop_no_brn",
              "ein_format_invalid",
              "ssn_format_invalid",
              "sole_prop_with_brn_will_be_cleared",
              "brn_format_invalid",
              "brn_has_suffix",
              "url_unreachable",
              "domain_lt_6_months",
              "registry_name_mismatch",
              "entity_type_mismatch",
              "registry_inactive",
              "registry_lt_6_months",
              "registry_no_match",
              "registry_unavailable"
            ]
          },
          "message": {
            "type": "string",
            "description": "What is wrong, for people."
          },
          "suggestion": {
            "type": "string",
            "description": "How to fix it. Absent when there is nothing to suggest."
          }
        },
        "required": [
          "severity",
          "field",
          "code",
          "message"
        ]
      },
      "PreflightProposedFix": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "description": "The candidate field to change. Known values: `useCase`, `state`, `contactPhone`, `entityType`, `brn`, `businessName`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "useCase",
              "state",
              "contactPhone",
              "entityType",
              "brn",
              "businessName"
            ]
          },
          "current": {
            "description": "The value sent. Absent when the field was not sent."
          },
          "proposed": {
            "type": "string",
            "description": "The value to send instead."
          },
          "reason": {
            "type": "string",
            "description": "Why, for people."
          }
        },
        "required": [
          "field",
          "proposed",
          "reason"
        ]
      },
      "PreflightReport": {
        "type": "object",
        "properties": {
          "verificationId": {
            "type": "string",
            "description": "`candidate`, or the `id` the request sent."
          },
          "businessName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The `businessName` sent, as sent. Absent when none was sent, `null` when `null` was sent."
          },
          "country": {
            "type": "string",
            "enum": [
              "CA",
              "US",
              "OTHER",
              "UNKNOWN"
            ],
            "description": "Whose checks ran: from `brnCountry`, then `addressCountry`. `OTHER` for another `brnCountry`, `UNKNOWN` when neither says."
          },
          "verdict": {
            "type": "string",
            "enum": [
              "ready",
              "warnings",
              "blocked"
            ],
            "description": "`blocked` when any issue is a blocker, `warnings` when any is a warning."
          },
          "domainAge": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "domain": {
                "type": "string",
                "description": "The website's domain, without `www.`."
              },
              "registrationDate": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "When the domain was registered, as the registry gives it."
              },
              "ageDays": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The domain's age in days."
              },
              "ageMonths": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The domain's age in months."
              }
            },
            "required": [
              "domain",
              "registrationDate",
              "ageDays",
              "ageMonths"
            ],
            "description": "The website's domain registration, `null` when no `website` was sent or the lookup failed. The date and ages are `null` when the registry did not say."
          },
          "registry": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "found": {
                "type": "boolean",
                "description": "Whether a matching registration was found."
              },
              "registeredName": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The name on the registration found."
              },
              "status": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The registration's status as the registry gives it, such as `Active`."
              }
            },
            "required": [
              "found",
              "registeredName",
              "status"
            ],
            "description": "The business registry lookup: British Columbia's registry for a Canadian business number, a US state registry for a US business that is not a sole proprietor. `null` when no lookup ran, or when the US lookup is not available. A Canadian lookup that fails reports `found: false`."
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreflightIssue"
            }
          },
          "proposedFixes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreflightProposedFix"
            }
          }
        },
        "required": [
          "verificationId",
          "country",
          "verdict",
          "domainAge",
          "registry",
          "issues",
          "proposedFixes"
        ]
      },
      "PresetTemplate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The template's id, such as `tpl_...`."
          },
          "name": {
            "type": "string",
            "description": "The template's name."
          },
          "text": {
            "type": "string",
            "description": "The message text, with `{{key}}` placeholders for its variables."
          },
          "variables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateVariable"
            },
            "description": "The `{{key}}` variables in the text, in order of first use. An empty array when there are none. An update that sets `variables` without `text` stores that array as sent instead."
          },
          "is_preset": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "preset_slug": {
            "type": [
              "string",
              "null"
            ],
            "description": "The preset's slug, such as `otp`. The column allows `null`, though every preset has one today."
          },
          "category": {
            "type": "string",
            "description": "What the preset is for. Known values: `otp`, `2fa`, `signup`, `transactional`, `general`, `marketing`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "otp",
              "2fa",
              "signup",
              "transactional",
              "general",
              "marketing"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "published"
            ]
          },
          "version": {
            "type": "integer",
            "description": "The template's version. Always 1 today."
          },
          "description": {
            "type": "string",
            "description": "What the preset is for. Empty for a preset without a description."
          },
          "published_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the template was published. `null` for a draft."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the template was created. ISO 8601, in UTC."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the template was last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "text",
          "variables",
          "is_preset",
          "preset_slug",
          "category",
          "status",
          "version",
          "description",
          "published_at",
          "created_at",
          "updated_at"
        ],
        "description": "One of Sendly's presets, which every account can preview, use and clone."
      },
      "PresetTemplateList": {
        "type": "object",
        "properties": {
          "templates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PresetTemplate"
            }
          }
        },
        "required": [
          "templates"
        ]
      },
      "PreviewMessageBatchRequest": {
        "type": "object",
        "properties": {
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "to": {
                  "type": "string",
                  "description": "The recipient, in E.164 format."
                },
                "text": {
                  "type": "string",
                  "description": "This recipient's text, in place of the shared `text`."
                }
              },
              "required": [
                "to"
              ]
            },
            "minItems": 1,
            "description": "The recipients, as `POST /api/v1/messages/batch` takes them."
          },
          "text": {
            "type": "string",
            "description": "The text for every recipient without its own."
          },
          "messageType": {
            "type": "string",
            "enum": [
              "marketing",
              "transactional"
            ],
            "description": "Defaults to `marketing`, which quiet hours apply to. Matched after trimming and ignoring case."
          },
          "channel": {
            "type": "string",
            "enum": [
              "sms"
            ],
            "description": "`sms`, or leave it out. Any other value, including `whatsapp` and `rcs`, is refused with `channel_not_supported`."
          }
        },
        "required": [
          "messages"
        ]
      },
      "ProvisionRateLimitError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "provision_rate_limit"
            ]
          },
          "message": {
            "type": "string"
          },
          "retryAfter": {
            "type": "integer",
            "description": "Seconds to wait before retrying."
          }
        },
        "required": [
          "error",
          "message",
          "retryAfter"
        ],
        "title": "provision_rate_limit",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "provision_rate_limit"
        ]
      },
      "RateLimitError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "rate_limit_exceeded"
            ]
          },
          "message": {
            "type": "string"
          },
          "retryAfter": {
            "type": "integer",
            "description": "Seconds to wait before retrying."
          }
        },
        "required": [
          "error",
          "message",
          "retryAfter"
        ],
        "title": "rate_limit_exceeded",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "rate_limit_exceeded"
        ]
      },
      "RcsAgent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The agent's id. Pass it as `agentId` on an RCS send."
          },
          "brandId": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "description": "Whether the agent can send: `testing` reaches invited test devices only, `approved` reaches everyone. Known values: `draft`, `submitted`, `testing`, `approved`, `suspended`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "submitted",
              "testing",
              "approved",
              "suspended"
            ]
          },
          "reviewStatus": {
            "type": "string",
            "description": "Where the registration is in Sendly's review and the launch that follows it. Known values: `draft`, `awaiting_review`, `changes_requested`, `approved_for_carrier`, `rejected`, `launch_requested`, `launch_submitted`, `launch_rejected`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "awaiting_review",
              "changes_requested",
              "approved_for_carrier",
              "rejected",
              "launch_requested",
              "launch_submitted",
              "launch_rejected",
              "failed"
            ]
          },
          "customerStage": {
            "type": "string",
            "description": "Where the registration is, in customer terms. Known values: `draft`, `in_review`, `changes_requested`, `rejected`, `brand_verification`, `agent_review`, `testing`, `launch_review`, `launching`, `launch_rejected`, `live`, `suspended`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "in_review",
              "changes_requested",
              "rejected",
              "brand_verification",
              "agent_review",
              "testing",
              "launch_review",
              "launching",
              "launch_rejected",
              "live",
              "suspended",
              "failed"
            ]
          },
          "displayName": {
            "type": "string",
            "description": "The agent's name. Empty until it is set."
          },
          "useCase": {
            "type": [
              "string",
              "null"
            ]
          },
          "hostingRegion": {
            "type": [
              "string",
              "null"
            ]
          },
          "basics": {
            "$ref": "#/components/schemas/RcsAgentBasics"
          },
          "campaign": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RcsCampaign"
              },
              {
                "type": "null"
              },
              {
                "type": "null"
              }
            ]
          },
          "testing": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RcsTesting"
              },
              {
                "type": "null"
              },
              {
                "type": "null"
              }
            ]
          },
          "reviewNote": {
            "type": [
              "string",
              "null"
            ],
            "description": "What Sendly's review asked to change."
          },
          "rejectionReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the carrier network did not approve the agent."
          },
          "testDevices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RcsTestDevice"
            }
          },
          "submittedForReviewAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the agent was submitted for review. ISO 8601, in UTC."
          },
          "basicsSubmittedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the profile was sent to the carrier network. ISO 8601, in UTC."
          },
          "launchSubmittedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the launch was sent to the carrier network. ISO 8601, in UTC."
          },
          "liveAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the agent went live. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the agent was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the agent last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "brandId",
          "status",
          "reviewStatus",
          "customerStage",
          "displayName",
          "useCase",
          "hostingRegion",
          "basics",
          "campaign",
          "testing",
          "reviewNote",
          "rejectionReason",
          "testDevices",
          "submittedForReviewAt",
          "basicsSubmittedAt",
          "launchSubmittedAt",
          "liveAt",
          "createdAt",
          "updatedAt"
        ],
        "description": "An RCS agent: the sender identity recipients see."
      },
      "RcsAgentBasics": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": "string",
            "description": "The agent's name, as recipients see it."
          },
          "useCase": {
            "type": [
              "string",
              "null"
            ],
            "description": "One of `MULTI_USE`, `PROMOTIONAL`, `TRANSACTIONAL`, `OTP` for review."
          },
          "hostingRegion": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "logoUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "heroUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "brandColor": {
            "type": [
              "string",
              "null"
            ],
            "description": "A hex color, such as `#2563EB`."
          },
          "privacyPolicyUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "termsAndConditionsUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "phoneNumber": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "number": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "website": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "email": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "address": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        },
        "required": [
          "displayName",
          "useCase",
          "hostingRegion"
        ],
        "description": "The agent's public profile. A field is present once it was sent."
      },
      "RcsAgentSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The agent's id. Pass it as `agentId` on an RCS send."
          },
          "name": {
            "type": "string",
            "description": "The agent's name. Empty until it is set."
          },
          "status": {
            "type": "string",
            "description": "Whether the agent can send: `testing` reaches invited test devices only, `approved` reaches everyone. Known values: `draft`, `submitted`, `testing`, `approved`, `suspended`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "submitted",
              "testing",
              "approved",
              "suspended"
            ]
          },
          "useCase": {
            "type": [
              "string",
              "null"
            ]
          },
          "sendable": {
            "type": "boolean",
            "description": "Whether the agent can send now: `testing` or `approved`, fully set up, and its brand has not failed carrier verification."
          },
          "displayName": {
            "type": "string",
            "description": "Same as `name`."
          },
          "stage": {
            "type": "string",
            "description": "Where the registration is, in customer terms. Known values: `draft`, `in_review`, `changes_requested`, `rejected`, `brand_verification`, `agent_review`, `testing`, `launch_review`, `launching`, `launch_rejected`, `live`, `suspended`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "in_review",
              "changes_requested",
              "rejected",
              "brand_verification",
              "agent_review",
              "testing",
              "launch_review",
              "launching",
              "launch_rejected",
              "live",
              "suspended",
              "failed"
            ]
          },
          "customerStage": {
            "type": "string",
            "description": "Same as `stage`.",
            "x-sendly-extensible-enum": [
              "draft",
              "in_review",
              "changes_requested",
              "rejected",
              "brand_verification",
              "agent_review",
              "testing",
              "launch_review",
              "launching",
              "launch_rejected",
              "live",
              "suspended",
              "failed"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the agent was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "useCase",
          "sendable",
          "displayName",
          "stage",
          "customerStage",
          "createdAt"
        ]
      },
      "RcsBrand": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The brand's id."
          },
          "reviewStatus": {
            "type": "string",
            "description": "Where the registration is in Sendly's review and the launch that follows it. Known values: `draft`, `awaiting_review`, `changes_requested`, `approved_for_carrier`, `rejected`, `launch_requested`, `launch_submitted`, `launch_rejected`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "awaiting_review",
              "changes_requested",
              "approved_for_carrier",
              "rejected",
              "launch_requested",
              "launch_submitted",
              "launch_rejected",
              "failed"
            ]
          },
          "customerStage": {
            "type": "string",
            "description": "Where the registration is, in customer terms. Known values: `draft`, `in_review`, `changes_requested`, `rejected`, `brand_verification`, `agent_review`, `testing`, `launch_review`, `launching`, `launch_rejected`, `live`, `suspended`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "in_review",
              "changes_requested",
              "rejected",
              "brand_verification",
              "agent_review",
              "testing",
              "launch_review",
              "launching",
              "launch_rejected",
              "live",
              "suspended",
              "failed"
            ]
          },
          "displayName": {
            "type": "string"
          },
          "legalName": {
            "type": "string"
          },
          "legalEntityType": {
            "type": "string",
            "description": "As sent. Submitting for review needs one of `LIMITED_LIABILITY_COMPANY`, `SOLE_PROPRIETORSHIP`, `PARTNERSHIP`, `CORPORATION`, `S_CORPORATION`. Empty on a draft created without it."
          },
          "organizationType": {
            "type": "string",
            "description": "As sent. Submitting for review needs one of `PRIVATE_PROFIT`, `PUBLIC_PROFIT`, `NON_PROFIT`, `GOVERNMENT`, `UNKNOWN`. Empty on a draft created without it."
          },
          "stockSymbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "`EXCHANGE:SYMBOL`, for a public company."
          },
          "websiteUrl": {
            "type": "string"
          },
          "ein": {
            "type": "string"
          },
          "address": {
            "type": "object",
            "properties": {
              "line1": {
                "type": "string"
              },
              "line2": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "city": {
                "type": "string"
              },
              "state": {
                "type": "string"
              },
              "postalCode": {
                "type": "string"
              },
              "countryCode": {
                "type": "string",
                "description": "`US` for every brand today."
              }
            },
            "required": [
              "line1",
              "line2",
              "city",
              "state",
              "postalCode",
              "countryCode"
            ]
          },
          "contact": {
            "type": "object",
            "properties": {
              "firstName": {
                "type": "string"
              },
              "lastName": {
                "type": "string"
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": "string"
              },
              "phoneNumber": {
                "type": "string"
              }
            },
            "required": [
              "firstName",
              "lastName",
              "title",
              "email",
              "phoneNumber"
            ]
          },
          "reviewNote": {
            "type": [
              "string",
              "null"
            ],
            "description": "What Sendly's review asked to change."
          },
          "rejectionReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the carrier network did not verify the brand."
          },
          "submittedForReviewAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the brand was submitted for review. ISO 8601, in UTC."
          },
          "sentToCarrierAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the brand was sent to the carrier network. ISO 8601, in UTC."
          },
          "verifiedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the carrier network verified the brand. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the brand was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the brand last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "reviewStatus",
          "customerStage",
          "displayName",
          "legalName",
          "legalEntityType",
          "organizationType",
          "stockSymbol",
          "websiteUrl",
          "ein",
          "address",
          "contact",
          "reviewNote",
          "rejectionReason",
          "submittedForReviewAt",
          "sentToCarrierAt",
          "verifiedAt",
          "createdAt",
          "updatedAt"
        ],
        "description": "An RCS brand: the business behind an agent. A field that was never sent is an empty string."
      },
      "RcsBusinessVerification": {
        "type": "object",
        "properties": {
          "verified": {
            "type": "boolean"
          },
          "state": {
            "type": "string",
            "description": "The workspace's business verification, from toll-free verification or its 10DLC brand. Known values: `verified`, `in_review`, `needs_attention`, `not_started`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "verified",
              "in_review",
              "needs_attention",
              "not_started"
            ]
          },
          "href": {
            "type": "string",
            "description": "The dashboard page that shows it."
          }
        },
        "required": [
          "verified",
          "state",
          "href"
        ],
        "description": "Whether the business is verified. Submitting for review needs `verified`."
      },
      "RcsCampaign": {
        "type": "object",
        "properties": {
          "companyOverview": {
            "type": [
              "string",
              "null"
            ]
          },
          "agentOverview": {
            "type": [
              "string",
              "null"
            ]
          },
          "interactions": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "interactionType": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "description": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "description": "`interactionType` is one of `TRANSACTIONAL_UPDATES`, `CUSTOMER_SUPPORT`, `LOYALTY_OR_REWARD`, `MARKETING_OR_PROMOTIONAL`, `ACCOUNT_ALERTS`, `TWO_WAY_CONVERSATION`, `OTHER`."
          },
          "messageExamples": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "consentSettings": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "optInMethods": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "object",
                  "properties": {
                    "methodType": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "description": "`methodType` is one of `SMS`, `WEBSITE`, `MOBILE_APP`, `QR_CODE`, `SALE_POINT`, `OTHER`."
              },
              "callToAction": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "callToActionUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "callToActionMediaUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "doubleOptIn": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "doubleOptInMessage": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "optInMessage": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "helpResponse": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "optOutResponse": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "additionalInformation": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "description": "How the agent will message people, which the launch review reads."
      },
      "RcsCapability": {
        "type": "object",
        "properties": {
          "to": {
            "type": "string",
            "description": "The number checked: `to` as sent when it starts with `+`, otherwise its digits after `+1` (10 digits) or `+`."
          },
          "agentId": {
            "type": "string",
            "description": "The agent the check ran as."
          },
          "capable": {
            "type": "boolean"
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The RCS features the number supports, as the carrier network names them. Empty when not capable."
          }
        },
        "required": [
          "to",
          "agentId",
          "capable",
          "features"
        ]
      },
      "RcsDossier": {
        "type": "object",
        "properties": {
          "brand": {
            "$ref": "#/components/schemas/RcsDossierBrand"
          },
          "usEligible": {
            "type": "boolean",
            "description": "Whether the business on file is in the US, or has no country on file."
          },
          "source": {
            "type": "string",
            "description": "Where `brand` came from: the workspace's 10DLC brand, its toll-free verification, or nothing. Known values: `tendlc`, `verification`, `none`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "tendlc",
              "verification",
              "none"
            ]
          },
          "verification": {
            "$ref": "#/components/schemas/RcsBusinessVerification"
          }
        },
        "required": [
          "brand",
          "usEligible",
          "source",
          "verification"
        ]
      },
      "RcsDossierBrand": {
        "type": "object",
        "properties": {
          "legalName": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "ein": {
            "type": "string"
          },
          "organizationType": {
            "type": "string"
          },
          "websiteUrl": {
            "type": "string"
          },
          "address": {
            "type": "object",
            "properties": {
              "line1": {
                "type": "string"
              },
              "line2": {
                "type": "string"
              },
              "city": {
                "type": "string"
              },
              "state": {
                "type": "string"
              },
              "postalCode": {
                "type": "string"
              },
              "countryCode": {
                "type": "string"
              }
            }
          },
          "contact": {
            "type": "object",
            "properties": {
              "firstName": {
                "type": "string"
              },
              "lastName": {
                "type": "string"
              },
              "email": {
                "type": "string"
              },
              "phoneNumber": {
                "type": "string"
              }
            }
          }
        },
        "description": "Brand fields already on file, shaped for `POST /api/v1/rcs/brands`. Only fields with a value are present."
      },
      "RcsInternalError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "rcs_internal_error"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "rcs_internal_error",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "rcs_internal_error"
        ]
      },
      "RcsNotEnabledError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "rcs_not_enabled"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "rcs_not_enabled",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "rcs_not_enabled"
        ]
      },
      "RcsRegistration": {
        "type": "object",
        "properties": {
          "brand": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RcsBrand"
              },
              {
                "type": "null"
              },
              {
                "type": "null"
              }
            ],
            "description": "The newest agent's brand, or the newest brand when there is no agent."
          },
          "agent": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RcsAgent"
              },
              {
                "type": "null"
              },
              {
                "type": "null"
              }
            ],
            "description": "The newest agent."
          },
          "devices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RcsTestDevice"
            },
            "description": "The newest agent's test devices."
          },
          "stage": {
            "type": "string",
            "description": "Where the registration is, in customer terms. Known values: `draft`, `in_review`, `changes_requested`, `rejected`, `brand_verification`, `agent_review`, `testing`, `launch_review`, `launching`, `launch_rejected`, `live`, `suspended`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "in_review",
              "changes_requested",
              "rejected",
              "brand_verification",
              "agent_review",
              "testing",
              "launch_review",
              "launching",
              "launch_rejected",
              "live",
              "suspended",
              "failed"
            ]
          },
          "brands": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RcsBrand"
            },
            "description": "Every brand on the workspace, newest first."
          },
          "agents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RcsAgent"
            },
            "description": "Every agent on the workspace, newest first, each with its own `customerStage` and test devices. `agent` is the first of these."
          },
          "usEligible": {
            "type": "boolean",
            "description": "Whether the business on file is in the US, or has no country on file."
          },
          "verification": {
            "$ref": "#/components/schemas/RcsBusinessVerification"
          }
        },
        "required": [
          "brand",
          "agent",
          "devices",
          "stage",
          "brands",
          "agents",
          "usEligible",
          "verification"
        ]
      },
      "RcsSendResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "channel": {
            "type": "string",
            "enum": [
              "rcs"
            ]
          },
          "message_format": {
            "type": "string",
            "enum": [
              "rcs"
            ]
          },
          "messageFormat": {
            "type": "string",
            "enum": [
              "rcs"
            ]
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "from": {
            "type": "string",
            "description": "The RCS agent's name."
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` for a card."
          },
          "status": {
            "type": "string",
            "enum": [
              "sent"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "outbound"
            ]
          },
          "segments": {
            "type": "integer",
            "description": "160-character segments for a text, or 1 for a rich card."
          },
          "creditsUsed": {
            "type": "integer"
          },
          "rcs": {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "text",
                  "card"
                ]
              },
              "agentId": {
                "type": "string"
              },
              "agentName": {
                "type": "string"
              }
            },
            "required": [
              "kind",
              "agentId",
              "agentName"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was created. ISO 8601, in UTC."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The custom metadata stored with the message, as sent."
          }
        },
        "required": [
          "id",
          "channel",
          "message_format",
          "messageFormat",
          "to",
          "from",
          "text",
          "status",
          "direction",
          "segments",
          "creditsUsed",
          "rcs",
          "createdAt",
          "metadata"
        ],
        "title": "RCS message sent",
        "x-sendly-visibility": "preview"
      },
      "RcsSmsFallbackResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "channel": {
            "type": "string",
            "enum": [
              "sms"
            ]
          },
          "fellBackTo": {
            "type": "string",
            "enum": [
              "sms"
            ]
          },
          "message_format": {
            "type": "string",
            "enum": [
              "sms"
            ]
          },
          "messageFormat": {
            "type": "string",
            "enum": [
              "sms"
            ]
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "from": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "sent"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "outbound"
            ]
          },
          "segments": {
            "type": "integer"
          },
          "creditsUsed": {
            "type": "integer"
          },
          "rcs": {
            "type": "object",
            "properties": {
              "requestedChannel": {
                "type": "string",
                "enum": [
                  "rcs"
                ]
              },
              "agentId": {
                "type": "string"
              },
              "fallbackReason": {
                "type": "string",
                "description": "Why the message went as an SMS. Known values: `not_rcs_capable`, `capability_check_failed`, `destination_not_supported`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "not_rcs_capable",
                  "capability_check_failed",
                  "destination_not_supported"
                ]
              },
              "suggestionsDropped": {
                "type": "boolean",
                "enum": [
                  true
                ],
                "description": "Present when suggestions were left out, since SMS has no form for them."
              }
            },
            "required": [
              "requestedChannel",
              "agentId",
              "fallbackReason"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was created. ISO 8601, in UTC."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The custom metadata stored with the message, as sent."
          }
        },
        "required": [
          "id",
          "channel",
          "fellBackTo",
          "message_format",
          "messageFormat",
          "to",
          "from",
          "text",
          "status",
          "direction",
          "segments",
          "creditsUsed",
          "rcs",
          "createdAt",
          "metadata"
        ],
        "title": "RCS requested, sent as SMS",
        "x-sendly-visibility": "preview"
      },
      "RcsTestDevice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The test device's id."
          },
          "phoneNumber": {
            "type": "string",
            "description": "The device's number, in E.164 format."
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "inviteStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` until the invitation is sent, once the agent is in testing.",
            "x-sendly-extensible-enum": [
              "PENDING",
              "ACCEPTED",
              "DECLINED"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the device was added. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "phoneNumber",
          "label",
          "inviteStatus",
          "createdAt"
        ]
      },
      "RcsTesting": {
        "type": "object",
        "properties": {
          "testUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "messageId": {
            "type": [
              "string",
              "null"
            ]
          },
          "additionalInformation": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "RcsValidationIssue": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "description": "The field, as a dotted path such as `brand.ein` or `devices.0.phoneNumber`."
          },
          "message": {
            "type": "string",
            "description": "What is wrong with it, for people."
          }
        },
        "required": [
          "path",
          "message"
        ]
      },
      "RedeliverWebhookRequest": {
        "type": "object",
        "properties": {
          "since": {
            "type": "string",
            "description": "The window's start. Defaults to 24 hours ago."
          },
          "until": {
            "type": "string",
            "description": "The window's end. Defaults to now."
          },
          "event_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Only deliveries of these event types."
          },
          "eventTypes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Takes precedence over `event_types`."
          },
          "statuses": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "failed",
                "cancelled",
                "delivered",
                "pending"
              ]
            },
            "description": "The delivery statuses to replay. Defaults to `failed` and `cancelled`."
          },
          "limit": {
            "type": "integer",
            "description": "At most this many deliveries, 1 to 10,000. Defaults to 1,000."
          }
        }
      },
      "RegisterEmergencyAddressRequest": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string",
            "description": "Street address. Required."
          },
          "unit": {
            "type": "string",
            "description": "Apartment, suite or unit."
          },
          "city": {
            "type": "string",
            "description": "Required."
          },
          "state": {
            "type": "string",
            "description": "The two-letter state or province code, in either case. Required."
          },
          "zip": {
            "type": "string",
            "description": "A five-digit ZIP (or ZIP+4) for the US, or a postal code like `A1A 1A1` for Canada. Required."
          },
          "country": {
            "type": "string",
            "enum": [
              "US",
              "CA"
            ],
            "description": "Defaults to `US`. Matched ignoring case."
          }
        },
        "required": [
          "street",
          "city",
          "state",
          "zip"
        ]
      },
      "RejectDraftRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "description": "Why the draft was rejected."
          }
        }
      },
      "RenameApiKeyRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "\\S",
            "description": "The new name. Trimmed; must hold more than spaces."
          }
        },
        "required": [
          "name"
        ]
      },
      "ReplyToConversationRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The message body. Required unless `mediaUrls` has a URL."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Up to 10 media URLs from `POST /api/v1/media`, which makes it an MMS."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Read when `mediaUrls` is absent."
          },
          "messageType": {
            "type": "string",
            "enum": [
              "marketing",
              "transactional"
            ],
            "description": "Defaults to `marketing`, which quiet hours apply to."
          },
          "message_type": {
            "type": "string",
            "enum": [
              "marketing",
              "transactional"
            ],
            "description": "Read when `messageType` is absent."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object, up to 4 KB serialized."
          },
          "from": {
            "type": "string",
            "description": "A sender number of this workspace, as for `POST /api/v1/messages`."
          }
        },
        "description": "Sent as an SMS or MMS to the conversation's phone number. `to` and `channel` are ignored."
      },
      "RequestBodyEncodingError": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "sendlyCode": {
            "type": "string",
            "enum": [
              "unsupported_content_type"
            ],
            "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
          }
        },
        "required": [
          "message"
        ],
        "description": "Sent by the JSON and form body parsers before authentication, with no `error` code: only the parser's own message.",
        "title": "Unreadable request body encoding",
        "x-sendly-error-shape": "codeless",
        "x-sendly-error-codes": [],
        "x-sendly-proposed-codes": [
          "unsupported_content_type"
        ]
      },
      "RequestBodyError": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "sendlyCode": {
            "type": "string",
            "enum": [
              "invalid_json"
            ],
            "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
          }
        },
        "required": [
          "message"
        ],
        "description": "Sent by the JSON and form body parsers before authentication, with no `error` code: only the parser's own message.",
        "title": "Unreadable request body",
        "x-sendly-error-shape": "codeless",
        "x-sendly-error-codes": [],
        "x-sendly-proposed-codes": [
          "invalid_json"
        ]
      },
      "RequestBodyTooLargeError": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "sendlyCode": {
            "type": "string",
            "enum": [
              "body_too_large"
            ],
            "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
          }
        },
        "required": [
          "message"
        ],
        "description": "Sent by the JSON and form body parsers before authentication, with no `error` code: only the parser's own message.",
        "title": "Request body too large",
        "x-sendly-error-shape": "codeless",
        "x-sendly-error-codes": [],
        "x-sendly-proposed-codes": [
          "body_too_large"
        ]
      },
      "RequestRcsLaunchRequest": {
        "type": "object",
        "properties": {
          "testUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Stored as `testing.testUrl` before the launch is checked."
          },
          "testingAdditionalInformation": {
            "type": [
              "string",
              "null"
            ],
            "description": "Stored as `testing.additionalInformation` before the launch is checked."
          }
        }
      },
      "ResendWhatsAppSignupCodeRequest": {
        "type": "object",
        "properties": {
          "verificationMethod": {
            "type": "string",
            "enum": [
              "sms",
              "voice"
            ],
            "description": "How to send the code. Defaults to `sms`."
          }
        }
      },
      "ResubmitWorkspaceUpgradeRequest": {
        "type": "object",
        "properties": {
          "businessName": {
            "type": "string",
            "maxLength": 500,
            "description": "The new entity's legal name."
          },
          "brn": {
            "type": "string",
            "maxLength": 500,
            "description": "The new entity's business registration number."
          },
          "brnType": {
            "type": "string",
            "enum": [
              "EIN",
              "SSN",
              "DUNS",
              "CRA",
              "VAT",
              "LEI",
              "OTHER"
            ],
            "description": "What kind of number `brn` is."
          },
          "brnCountry": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "description": "The ISO 3166-1 alpha-2 country that issued `brn`, in capitals."
          },
          "entityType": {
            "type": "string",
            "enum": [
              "SOLE_PROPRIETOR",
              "PRIVATE_PROFIT",
              "PUBLIC_PROFIT",
              "NON_PROFIT",
              "GOVERNMENT"
            ],
            "description": "The new entity's legal form."
          },
          "doingBusinessAs": {
            "type": "string",
            "maxLength": 500,
            "description": "A trading name, if it differs from `businessName`."
          },
          "website": {
            "type": "string",
            "maxLength": 500,
            "description": "The business website, with its scheme (`https://`)."
          },
          "address1": {
            "type": "string",
            "maxLength": 500,
            "description": "The first line of the business address."
          },
          "address2": {
            "type": "string",
            "maxLength": 500,
            "description": "The second line of the business address."
          },
          "city": {
            "type": "string",
            "maxLength": 500,
            "description": "The business address's city."
          },
          "state": {
            "type": "string",
            "maxLength": 500,
            "description": "The state or province. A 2-letter US or Canadian code is changed to the full name."
          },
          "zip": {
            "type": "string",
            "maxLength": 500,
            "description": "The ZIP or postal code."
          },
          "addressCountry": {
            "type": "string",
            "description": "The address's ISO 3166-1 alpha-2 country code."
          },
          "contactFirstName": {
            "type": "string",
            "maxLength": 500,
            "description": "The contact's first name."
          },
          "contactLastName": {
            "type": "string",
            "maxLength": 500,
            "description": "The contact's last name."
          },
          "contactEmail": {
            "type": "string",
            "maxLength": 500,
            "description": "The contact's email address."
          },
          "contactPhone": {
            "type": "string",
            "maxLength": 500,
            "description": "The contact's phone number, in E.164 format."
          },
          "monthlyVolume": {
            "type": "string",
            "enum": [
              "10",
              "100",
              "1,000",
              "10,000",
              "100,000",
              "250,000",
              "500,000",
              "750,000",
              "1,000,000",
              "5,000,000",
              "10,000,000+"
            ],
            "description": "Expected messages a month."
          },
          "useCase": {
            "type": "string",
            "enum": [
              "2FA",
              "App Notifications",
              "Appointments",
              "Auctions",
              "Auto Repair Services",
              "Bank Transfers",
              "Billing",
              "Booking Confirmations",
              "Business Updates",
              "COVID-19 Alerts",
              "Career Training",
              "Chatbot",
              "Conversational / Alerts",
              "Courier Services & Deliveries",
              "Emergency Alerts",
              "Events & Planning",
              "Financial Services",
              "Fraud Alerts",
              "Fundraising",
              "General Marketing",
              "General School Updates",
              "HR / Staffing",
              "Healthcare Alerts",
              "Housing Community Updates",
              "Insurance Services",
              "Job Dispatch",
              "Legal Services",
              "Mixed",
              "Motivational Reminders",
              "Notary Notifications",
              "Order Notifications",
              "Political",
              "Public Works",
              "Real Estate Services",
              "Religious Services",
              "Repair and Diagnostics Alerts",
              "Rewards Program",
              "Surveys",
              "System Alerts",
              "Voting Reminders",
              "Waitlist Alerts",
              "Webinar Reminders",
              "Workshop Alerts"
            ],
            "description": "The messaging use case."
          },
          "useCaseSummary": {
            "type": "string",
            "maxLength": 500,
            "description": "What the messages are for, in a sentence or two."
          },
          "sampleMessages": {
            "type": "string",
            "maxLength": 1000,
            "description": "Example messages the workspace will send, with STOP opt-out language."
          },
          "optInWorkflow": {
            "type": "string",
            "maxLength": 500,
            "description": "How recipients agree to receive messages."
          },
          "privacyUrl": {
            "type": "string",
            "maxLength": 500,
            "description": "The privacy policy's URL."
          },
          "termsUrl": {
            "type": "string",
            "maxLength": 500,
            "description": "The terms and conditions' URL."
          },
          "additionalInformation": {
            "type": "string",
            "maxLength": 500,
            "description": "Anything else the reviewer should know."
          },
          "ageGatedContent": {
            "type": "string",
            "enum": [
              "true",
              "false"
            ],
            "description": "`true` when the messages are for adults only. Read as the string `true` or `false`: a JSON boolean is ignored on a start, and counts as `false` on a resubmit."
          }
        },
        "description": "Only the fields to change; the rest keep their pending values. The same fields can be sent as `multipart/form-data`, with a replacement registration document as the file field `einDoc` (a PDF or image, up to 10 MB)."
      },
      "RevokeApiKeyRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "description": "Why the key was revoked, kept with it."
          }
        }
      },
      "RevokedApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The API key's id."
          },
          "name": {
            "type": "string"
          },
          "revoked": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "revokedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was revoked. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "revoked",
          "revokedAt"
        ]
      },
      "RotateApiKeyRequest": {
        "type": "object",
        "properties": {
          "gracePeriodHours": {
            "type": "number",
            "minimum": 24,
            "maximum": 168,
            "description": "How long the old key keeps working, 24 to 168 hours. Defaults to 24. A numeric string is read as a number."
          }
        }
      },
      "RotatedApiKey": {
        "type": "object",
        "properties": {
          "newKey": {
            "$ref": "#/components/schemas/RotatedNewKey"
          },
          "oldKey": {
            "$ref": "#/components/schemas/RotatedOldKey"
          },
          "message": {
            "type": "string",
            "description": "Says when the old key expires, such as `Old key will expire in 24 hours`."
          }
        },
        "required": [
          "newKey",
          "oldKey",
          "message"
        ]
      },
      "RotatedNewKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The API key's id."
          },
          "userId": {
            "type": "string",
            "description": "The user who owns the key."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace the key belongs to. `null` for a personal key."
          },
          "name": {
            "type": "string"
          },
          "keyId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The key's public reference id."
          },
          "keyPrefix": {
            "type": [
              "string",
              "null"
            ],
            "description": "The key's first 12 characters."
          },
          "type": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "description": "`test` simulates every send and never charges; `live` sends."
          },
          "scopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "description": "A permission the key holds. `enterprise:master` belongs to an enterprise master key only, and no key can grant it. `full` is a legacy scope an older key may hold; a rotation keeps it. Known values: `sms:send`, `sms:read`, `verify:send`, `verify:read`, `webhooks:read`, `webhooks:write`, `templates:read`, `templates:write`, `campaigns:read`, `campaigns:write`, `campaigns:send`, `contacts:read`, `contacts:write`, `numbers:read`, `numbers:write`, `tendlc:read`, `tendlc:write`, `rcs:read`, `rcs:write`, `whatsapp:read`, `whatsapp:write`, `short_codes:read`, `short_codes:write`, `links:read`, `links:write`, `calls:read`, `calls:write`, `enterprise:master`, `full`. More can be added at any time, so treat an unknown value as valid.",
              "x-sendly-extensible-enum": [
                "sms:send",
                "sms:read",
                "verify:send",
                "verify:read",
                "webhooks:read",
                "webhooks:write",
                "templates:read",
                "templates:write",
                "campaigns:read",
                "campaigns:write",
                "campaigns:send",
                "contacts:read",
                "contacts:write",
                "numbers:read",
                "numbers:write",
                "tendlc:read",
                "tendlc:write",
                "rcs:read",
                "rcs:write",
                "whatsapp:read",
                "whatsapp:write",
                "short_codes:read",
                "short_codes:write",
                "links:read",
                "links:write",
                "calls:read",
                "calls:write",
                "enterprise:master",
                "full"
              ]
            },
            "description": "The permissions the key holds."
          },
          "source": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where the key was created. Known values: `manual`, `onboarding`, `cli_quickstart`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "manual",
              "onboarding",
              "cli_quickstart"
            ]
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key stops working: the expiry it was created with, or the end of a rotation's grace period. ISO 8601, in UTC."
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was last used. ISO 8601, in UTC."
          },
          "isActive": {
            "type": "boolean"
          },
          "revokedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was revoked. ISO 8601, in UTC."
          },
          "revokedReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "rotatedFromId": {
            "type": "string",
            "description": "The key this one replaced."
          },
          "gracePeriodHours": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The stored grace period, 24 unless set. A rotation does not write it."
          },
          "isEnterpriseMaster": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was created. ISO 8601, in UTC."
          },
          "key": {
            "type": "string",
            "description": "The new full secret key. It is shown only here, once: store it securely."
          },
          "warning": {
            "type": "string",
            "enum": [
              "This key will only be shown once. Store it securely."
            ]
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "name",
          "keyId",
          "keyPrefix",
          "type",
          "scopes",
          "source",
          "expiresAt",
          "lastUsedAt",
          "isActive",
          "revokedAt",
          "revokedReason",
          "rotatedFromId",
          "gracePeriodHours",
          "isEnterpriseMaster",
          "createdAt",
          "key",
          "warning"
        ],
        "description": "The replacement key, as stored, with its secret. Its name is the old name followed by ` (rotated)`, and it has the old key's scopes."
      },
      "RotatedOldKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The API key's id."
          },
          "userId": {
            "type": "string",
            "description": "The user who owns the key."
          },
          "organizationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace the key belongs to. `null` for a personal key."
          },
          "name": {
            "type": "string"
          },
          "keyId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The key's public reference id."
          },
          "keyPrefix": {
            "type": [
              "string",
              "null"
            ],
            "description": "The key's first 12 characters."
          },
          "type": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "description": "`test` simulates every send and never charges; `live` sends."
          },
          "scopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "description": "A permission the key holds. `enterprise:master` belongs to an enterprise master key only, and no key can grant it. `full` is a legacy scope an older key may hold; a rotation keeps it. Known values: `sms:send`, `sms:read`, `verify:send`, `verify:read`, `webhooks:read`, `webhooks:write`, `templates:read`, `templates:write`, `campaigns:read`, `campaigns:write`, `campaigns:send`, `contacts:read`, `contacts:write`, `numbers:read`, `numbers:write`, `tendlc:read`, `tendlc:write`, `rcs:read`, `rcs:write`, `whatsapp:read`, `whatsapp:write`, `short_codes:read`, `short_codes:write`, `links:read`, `links:write`, `calls:read`, `calls:write`, `enterprise:master`, `full`. More can be added at any time, so treat an unknown value as valid.",
              "x-sendly-extensible-enum": [
                "sms:send",
                "sms:read",
                "verify:send",
                "verify:read",
                "webhooks:read",
                "webhooks:write",
                "templates:read",
                "templates:write",
                "campaigns:read",
                "campaigns:write",
                "campaigns:send",
                "contacts:read",
                "contacts:write",
                "numbers:read",
                "numbers:write",
                "tendlc:read",
                "tendlc:write",
                "rcs:read",
                "rcs:write",
                "whatsapp:read",
                "whatsapp:write",
                "short_codes:read",
                "short_codes:write",
                "links:read",
                "links:write",
                "calls:read",
                "calls:write",
                "enterprise:master",
                "full"
              ]
            },
            "description": "The permissions the key holds."
          },
          "source": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where the key was created. Known values: `manual`, `onboarding`, `cli_quickstart`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "manual",
              "onboarding",
              "cli_quickstart"
            ]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the old key stops working: the end of the grace period. ISO 8601, in UTC."
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was last used. ISO 8601, in UTC."
          },
          "isActive": {
            "type": "boolean"
          },
          "revokedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the key was revoked. ISO 8601, in UTC."
          },
          "revokedReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "rotatedFromId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The key this one replaced, for a rotated key."
          },
          "gracePeriodHours": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The stored grace period, 24 unless set. A rotation does not write it."
          },
          "isEnterpriseMaster": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "userId",
          "organizationId",
          "name",
          "keyId",
          "keyPrefix",
          "type",
          "scopes",
          "source",
          "expiresAt",
          "lastUsedAt",
          "isActive",
          "revokedAt",
          "revokedReason",
          "rotatedFromId",
          "gracePeriodHours",
          "isEnterpriseMaster",
          "createdAt"
        ],
        "description": "The key that was rotated, as stored, without its hash. It keeps working until `expiresAt`."
      },
      "SandboxVerificationResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The verification's id."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending"
            ]
          },
          "phone": {
            "type": "string",
            "description": "The phone number, as sent in `to`."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the code expires. ISO 8601, in UTC."
          },
          "sandbox": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "sandbox_code": {
            "type": "string",
            "description": "The code, for a test key only. Check it to complete the verification."
          },
          "message": {
            "type": "string",
            "description": "Says that no SMS was sent."
          }
        },
        "required": [
          "id",
          "status",
          "phone",
          "expires_at",
          "sandbox",
          "sandbox_code",
          "message"
        ],
        "title": "Sandbox code created"
      },
      "SavedTemplate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The template's id, such as `tpl_...`."
          },
          "name": {
            "type": "string",
            "description": "The template's name."
          },
          "text": {
            "type": "string",
            "description": "The message text, with `{{key}}` placeholders for its variables."
          },
          "variables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateVariable"
            },
            "description": "The `{{key}}` variables in the text, in order of first use. An empty array when there are none. An update that sets `variables` without `text` stores that array as sent instead."
          },
          "is_preset": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "status": {
            "type": "string",
            "description": "`draft` can still be edited; `published` is locked. Known values: `draft`, `published`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "published"
            ]
          },
          "version": {
            "type": "integer",
            "description": "The template's version. Always 1 today."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the template was created. ISO 8601, in UTC."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the template was last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "text",
          "variables",
          "is_preset",
          "status",
          "version",
          "created_at",
          "updated_at"
        ],
        "description": "One of your templates, as creating or updating returns it: a `Template` without `preset_slug` or `published_at`."
      },
      "ScheduleCampaignRequest": {
        "type": "object",
        "properties": {
          "scheduledAt": {
            "type": "string",
            "format": "date-time",
            "description": "When to send, in the future. ISO 8601."
          },
          "timezone": {
            "type": "string",
            "description": "Stored with the schedule. Defaults to `America/New_York`."
          }
        },
        "required": [
          "scheduledAt"
        ]
      },
      "ScheduleMessageRequest": {
        "type": "object",
        "properties": {
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format, such as `+15555550100`."
          },
          "text": {
            "type": "string",
            "description": "The message body, also when `mediaUrls` is set."
          },
          "scheduledAt": {
            "type": "string",
            "description": "When to send: an ISO 8601 timestamp at least 5 minutes and at most 5 days from now. It is kept as asked, even inside the recipient's quiet hours."
          },
          "timezone": {
            "type": "string",
            "description": "Stored with the message and returned as sent. It does not change how `scheduledAt` is read. Defaults to `UTC`."
          },
          "from": {
            "type": "string",
            "description": "A sender number from this workspace. Without it, the number pool picks one."
          },
          "messageType": {
            "type": "string",
            "enum": [
              "marketing",
              "transactional"
            ],
            "description": "Defaults to `marketing`, which quiet hours apply to. Matched after trimming and ignoring case."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object, stored with the scheduled message."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Up to 10 media URLs from `POST /api/v1/media`, which makes the message an MMS. US and Canada only."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Read when `mediaUrls` is absent."
          },
          "channel": {
            "type": "string",
            "enum": [
              "sms"
            ],
            "description": "`sms`, or leave it out. Any other value, including `whatsapp` and `rcs`, is refused with `channel_not_supported`."
          }
        },
        "required": [
          "to",
          "text",
          "scheduledAt"
        ]
      },
      "ScheduledMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The scheduled message's id."
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "text": {
            "type": "string",
            "description": "The text as sent."
          },
          "scheduledAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message goes, or went. ISO 8601, in UTC."
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ],
            "description": "The `timezone` the message was scheduled with."
          },
          "status": {
            "type": "string",
            "description": "Where the scheduled message is: `scheduled` until it goes, `cancelled` once cancelled, `failed` when the carrier refused to schedule it, and after that the status of its delivery receipts. Known values: `scheduled`, `sent`, `delivered`, `failed`, `bounced`, `cancelled`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "scheduled",
              "sent",
              "delivered",
              "failed",
              "bounced",
              "cancelled"
            ]
          },
          "creditsReserved": {
            "type": "integer",
            "description": "Credits charged when it was scheduled."
          },
          "segments": {
            "type": "integer"
          },
          "senderType": {
            "type": "string",
            "enum": [
              "number_pool",
              "alphanumeric"
            ],
            "description": "Decided by the destination alone, even when `from` was sent: `number_pool` for the US or Canada, `alphanumeric` for any other."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was scheduled. ISO 8601, in UTC."
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why scheduling or delivery failed, when it did."
          },
          "cancelledAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was cancelled. ISO 8601, in UTC."
          },
          "sentAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was sent. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "to",
          "text",
          "scheduledAt",
          "timezone",
          "status",
          "creditsReserved",
          "segments",
          "senderType",
          "createdAt",
          "error",
          "cancelledAt",
          "sentAt"
        ],
        "description": "A scheduled message, as `GET /api/v1/messages/scheduled/{id}` returns it."
      },
      "ScheduledMessageCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The scheduled message's id, `schd_` and 32 hex characters."
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "text": {
            "type": "string",
            "description": "The text as sent."
          },
          "scheduledAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message will go: the time asked for. ISO 8601, in UTC."
          },
          "timezone": {
            "type": "string",
            "description": "The `timezone` sent, or `UTC`."
          },
          "status": {
            "type": "string",
            "enum": [
              "scheduled"
            ]
          },
          "creditsReserved": {
            "type": "integer",
            "description": "Credits charged now, refunded if the message is cancelled or fails."
          },
          "segments": {
            "type": "integer",
            "description": "SMS segments the text needs. 1 for an MMS."
          },
          "senderType": {
            "type": "string",
            "enum": [
              "number_pool",
              "alphanumeric"
            ],
            "description": "Decided by the destination alone, even when `from` was sent: `number_pool` for the US or Canada, `alphanumeric` for any other."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was scheduled. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "to",
          "text",
          "scheduledAt",
          "timezone",
          "status",
          "creditsReserved",
          "segments",
          "senderType",
          "createdAt"
        ]
      },
      "ScheduledMessageList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScheduledMessageSummary"
            }
          },
          "count": {
            "type": "integer",
            "description": "How many items are in this response."
          }
        },
        "required": [
          "data",
          "count"
        ]
      },
      "ScheduledMessageSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The scheduled message's id."
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "text": {
            "type": "string",
            "description": "The text as sent."
          },
          "scheduledAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message goes, or went. ISO 8601, in UTC."
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ],
            "description": "The `timezone` the message was scheduled with."
          },
          "status": {
            "type": "string",
            "description": "Where the scheduled message is: `scheduled` until it goes, `cancelled` once cancelled, `failed` when the carrier refused to schedule it, and after that the status of its delivery receipts. Known values: `scheduled`, `sent`, `delivered`, `failed`, `bounced`, `cancelled`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "scheduled",
              "sent",
              "delivered",
              "failed",
              "bounced",
              "cancelled"
            ]
          },
          "creditsReserved": {
            "type": "integer",
            "description": "Credits charged when it was scheduled."
          },
          "segments": {
            "type": "integer"
          },
          "senderType": {
            "type": "string",
            "enum": [
              "number_pool",
              "alphanumeric"
            ],
            "description": "Decided by the destination alone, even when `from` was sent: `number_pool` for the US or Canada, `alphanumeric` for any other."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was scheduled. ISO 8601, in UTC."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The metadata stored with it. `{}` when none was sent."
          }
        },
        "required": [
          "id",
          "to",
          "text",
          "scheduledAt",
          "timezone",
          "status",
          "creditsReserved",
          "segments",
          "senderType",
          "createdAt",
          "metadata"
        ],
        "description": "A scheduled message, as `GET /api/v1/messages/scheduled` lists it."
      },
      "SendCampaignRequest": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "description": "An active phone number of this workspace to send from. Without it, the number pool picks the sender."
          }
        }
      },
      "SendGroupMessageRequest": {
        "type": "object",
        "properties": {
          "to": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 2,
            "maxItems": 8,
            "description": "2 to 8 distinct US or Canada recipients, in E.164 format."
          },
          "text": {
            "type": "string",
            "description": "Required unless `mediaUrls` has a URL."
          },
          "from": {
            "type": "string",
            "description": "A sender number from this workspace. Without it, the workspace's default."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Up to 10 media URLs from `POST /api/v1/media`."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Read when `mediaUrls` is absent."
          },
          "messageType": {
            "type": "string",
            "enum": [
              "marketing",
              "transactional"
            ],
            "description": "Defaults to `transactional` here. Only `marketing` is held to quiet hours. Matched after trimming and ignoring case."
          },
          "channel": {
            "type": "string",
            "enum": [
              "sms"
            ],
            "description": "`sms`, or leave it out. Any other value, including `whatsapp` and `rcs`, is refused with `channel_not_supported`."
          }
        },
        "required": [
          "to"
        ],
        "x-sendly-visibility": "preview"
      },
      "SendMessageBatchRequest": {
        "type": "object",
        "properties": {
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "to": {
                  "type": "string",
                  "description": "The recipient, in E.164 format."
                },
                "text": {
                  "type": "string",
                  "description": "This recipient's text, in place of the shared `text`."
                }
              },
              "required": [
                "to"
              ]
            },
            "minItems": 1,
            "maxItems": 10000,
            "description": "1 to 10,000 recipients. A recipient who opted out, or whose number is flagged as unable to receive texts, is skipped."
          },
          "text": {
            "type": "string",
            "description": "The text for every recipient without its own. Required unless each has one, also with media."
          },
          "from": {
            "type": "string",
            "description": "A sender number from this workspace, for every message."
          },
          "messageType": {
            "type": "string",
            "enum": [
              "marketing",
              "transactional"
            ],
            "description": "Defaults to `marketing`, which quiet hours apply to. Matched after trimming and ignoring case."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object, stored on every message."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Up to 10 media URLs from `POST /api/v1/media`, which makes every message an MMS. US and Canada only."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Read when `mediaUrls` is absent."
          },
          "uploadId": {
            "type": "string",
            "description": "The CSV upload the recipients came from, which is then linked to the batch."
          },
          "upload_id": {
            "type": "string",
            "description": "Read when `uploadId` is absent."
          },
          "channel": {
            "type": "string",
            "enum": [
              "sms"
            ],
            "description": "`sms`, or leave it out. Any other value, including `whatsapp` and `rcs`, is refused with `channel_not_supported`."
          }
        },
        "required": [
          "messages"
        ]
      },
      "SendMessageRequest": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/SendSmsRequest"
          },
          {
            "$ref": "#/components/schemas/SendWhatsAppRequest"
          },
          {
            "$ref": "#/components/schemas/SendRcsRequest"
          }
        ],
        "description": "The `channel` field picks the shape. Without it, the message is an SMS."
      },
      "SendRcsRequest": {
        "type": "object",
        "properties": {
          "channel": {
            "type": "string",
            "enum": [
              "rcs"
            ]
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "agentId": {
            "type": "string",
            "description": "The RCS agent to send from. Required when the workspace has more than one."
          },
          "text": {
            "type": "string"
          },
          "suggestions": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "object",
                  "properties": {
                    "reply": {
                      "type": "object",
                      "properties": {
                        "text": {
                          "type": "string"
                        },
                        "postbackData": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "text",
                        "postbackData"
                      ]
                    }
                  },
                  "required": [
                    "reply"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "action": {
                      "type": "object",
                      "properties": {
                        "text": {
                          "type": "string"
                        },
                        "postbackData": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "text",
                        "postbackData",
                        "url"
                      ]
                    }
                  },
                  "required": [
                    "action"
                  ]
                }
              ]
            },
            "description": "Suggested replies and actions, on a text message only."
          },
          "card": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "mediaUrl": {
                "type": "string",
                "description": "A public JPEG, PNG or GIF image URL."
              },
              "orientation": {
                "type": "string",
                "enum": [
                  "vertical",
                  "horizontal"
                ]
              },
              "suggestions": {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "reply": {
                          "type": "object",
                          "properties": {
                            "text": {
                              "type": "string"
                            },
                            "postbackData": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "text",
                            "postbackData"
                          ]
                        }
                      },
                      "required": [
                        "reply"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "action": {
                          "type": "object",
                          "properties": {
                            "text": {
                              "type": "string"
                            },
                            "postbackData": {
                              "type": "string"
                            },
                            "url": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "text",
                            "postbackData",
                            "url"
                          ]
                        }
                      },
                      "required": [
                        "action"
                      ]
                    }
                  ]
                }
              }
            },
            "required": [
              "title",
              "description"
            ],
            "description": "A rich card, in place of `text`. A card has no SMS form, so it never falls back."
          },
          "fallbackToSms": {
            "type": "boolean",
            "description": "Defaults to `true`: a text to a recipient without RCS goes as an SMS, billed as one."
          },
          "messageType": {
            "type": "string",
            "description": "`transactional`, the default, or `marketing`, matched after trimming and ignoring case; any other value counts as `transactional`. It applies to the RCS message and to an SMS fallback. During the recipient's quiet hours a `marketing` message is refused with `compliance_blocked`, and a `transactional` one that reads as promotional with `TRANSACTIONAL_MARKETING_MISMATCH`."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object."
          }
        },
        "required": [
          "channel",
          "to"
        ],
        "description": "Exactly one of `text` or `card`. Behind the `rcs_channel` flag, and live keys only.",
        "title": "RCS",
        "x-sendly-visibility": "preview"
      },
      "SendSmsRequest": {
        "type": "object",
        "properties": {
          "to": {
            "type": "string",
            "pattern": "^\\+[1-9]\\d{6,14}$",
            "description": "The recipient, in E.164 format, such as `+15555550100`."
          },
          "text": {
            "type": "string",
            "description": "The message body. Required unless `mediaUrls` has at least one URL."
          },
          "from": {
            "type": "string",
            "description": "A sender number from this workspace: active and, for a US local number, assigned to a 10DLC campaign. A 5 or 6 digit value sends from the workspace's short code when short codes are enabled. For an international destination, a `from` that cannot be used there is replaced by the account's sender ID, and `warning` says so."
          },
          "messageType": {
            "type": "string",
            "enum": [
              "marketing",
              "transactional"
            ],
            "description": "Defaults to `marketing`, which quiet hours apply to. Matched after trimming and ignoring case."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object, up to 4 KB serialized. Returned on the message and in webhooks."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Up to 10 media URLs from `POST /api/v1/media`, which makes the message an MMS. US and Canada only."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 10,
            "description": "Read when `mediaUrls` is absent."
          },
          "channel": {
            "type": "string",
            "enum": [
              "sms"
            ],
            "description": "`sms`, the default. An empty value means `sms` too."
          }
        },
        "required": [
          "to"
        ],
        "title": "SMS or MMS"
      },
      "SendVerificationRequest": {
        "type": "object",
        "properties": {
          "to": {
            "type": "string",
            "pattern": "^\\+[1-9]\\d{6,14}$",
            "description": "The phone number to send the code to, in E.164 format, such as `+15555550100`. The server checks it against its country's numbering plan, so it refuses a fictional number like this example, and it also takes the number with spaces."
          },
          "template_id": {
            "type": "string",
            "description": "A published template of this workspace, or a preset, with `{{code}}` and `{{app_name}}`. Defaults to the profile's template, then to `tpl_preset_otp`."
          },
          "profile_id": {
            "type": "string",
            "description": "A verify profile of this workspace. Its template, app name, timeout and code length apply unless the request sets them, and its `max_attempts` and `allowed_countries` always apply."
          },
          "app_name": {
            "type": "string",
            "description": "The app name in the message. Defaults to the profile's, then to the account's brand name, then to its sender ID or business name, then to `App`."
          },
          "timeout_secs": {
            "type": "integer",
            "description": "Seconds until the code expires, 60 to 3,600; a value outside is clamped. Defaults to the profile's, then to 300. A value that is not a positive integer means the default."
          },
          "code_length": {
            "type": "integer",
            "description": "Digits in the code, 4 to 10; a value outside is clamped. Defaults to the profile's, then to 6. A value that is not a positive integer means the default."
          },
          "channel": {
            "type": "string",
            "enum": [
              "sms"
            ],
            "description": "`sms`, the default. An empty value means `sms` too. Any other value is refused."
          }
        },
        "required": [
          "to"
        ]
      },
      "SendWhatsAppRequest": {
        "type": "object",
        "properties": {
          "channel": {
            "type": "string",
            "enum": [
              "whatsapp"
            ]
          },
          "from": {
            "type": "string",
            "description": "The workspace's WhatsApp sender number, in E.164 format."
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "text": {
            "type": "string",
            "description": "A text message, up to 4,096 bytes. Needs an open 24-hour window."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "One media URL. Needs an open 24-hour window."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Read when `mediaUrls` is absent."
          },
          "caption": {
            "type": "string",
            "description": "A caption for an image, video or document, up to 1,024 bytes. With media, `text` is sent as the caption."
          },
          "template": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "language": {
                "type": "string",
                "description": "The template's language code, such as `en_US`."
              },
              "variables": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Body variables by position: `{\"1\": \"Ada\"}` fills `{{1}}`."
              },
              "buttons": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer"
                    },
                    "variables": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "index",
                    "variables"
                  ]
                },
                "description": "URL button variables, by the button's index."
              }
            },
            "required": [
              "name",
              "language"
            ],
            "description": "An approved template. Opens a conversation outside the 24-hour window."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Your own JSON object, up to 4 KB serialized."
          },
          "fallbackToSms": {
            "type": "boolean",
            "description": "Defaults to `false`. When `true`, a message WhatsApp can't deliver goes as an SMS from the same number, billed as one: when the 24-hour window is closed, when WhatsApp refuses it, or when WhatsApp reports it undeliverable later. The number must be able to send SMS to the recipient (US and Canada only), or the send is refused with `sms_fallback_unavailable`. Marketing and authentication templates, and media without a caption, can't fall back (`sms_fallback_not_supported`). A template falls back as its text header, body and footer with the variables filled in, and its URL and phone buttons as `label: target`."
          }
        },
        "required": [
          "channel",
          "from",
          "to"
        ],
        "description": "Exactly one of `text`, `mediaUrls` or `template`. Behind the `whatsapp_channel` flag, and live keys only.",
        "title": "WhatsApp",
        "x-sendly-visibility": "preview"
      },
      "ServerError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "server_error"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "server_error",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "server_error"
        ]
      },
      "SessionAuthenticationError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "unauthorized"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "unauthorized: no usable credentials",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "unauthorized"
        ]
      },
      "SetEnterpriseWebhookRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "An `https://` URL on a public host: not localhost or a private or reserved address."
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The event types to send. Left out keeps the current filter."
          },
          "workspaces": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The workspace ids whose events are sent. Left out keeps the current filter."
          }
        },
        "required": [
          "url"
        ]
      },
      "SetRcsTestDevicesRequest": {
        "type": "object",
        "properties": {
          "devices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "phoneNumber": {
                  "type": "string",
                  "description": "In E.164 format. A 10-digit number without `+` is read as a US number."
                },
                "label": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "phoneNumber"
              ]
            },
            "maxItems": 20,
            "description": "Every test device the agent should have, up to 20."
          }
        },
        "required": [
          "devices"
        ]
      },
      "ShortCode": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The application's id."
          },
          "shortCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "The code's digits. `null` until Sendly assigns a code."
          },
          "countryCode": {
            "type": "string",
            "description": "Always `US` today."
          },
          "status": {
            "type": "string",
            "description": "Where the code is in provisioning. Only `active` can send. Known values: `requested`, `provisioning`, `parked`, `active`, `suspended`, `cancelled`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "requested",
              "provisioning",
              "parked",
              "active",
              "suspended",
              "cancelled"
            ]
          },
          "reviewStatus": {
            "type": "string",
            "description": "Where Sendly's review of the application stands. Known values: `draft`, `awaiting_review`, `changes_requested`, `approved_for_filing`, `filed`, `rejected`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "awaiting_review",
              "changes_requested",
              "approved_for_filing",
              "filed",
              "rejected"
            ]
          },
          "useCase": {
            "type": "string",
            "description": "What the code is for, as the customer wrote it."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the application was started. ISO 8601, in UTC."
          },
          "billing": {
            "$ref": "#/components/schemas/ShortCodeListBilling"
          }
        },
        "required": [
          "id",
          "shortCode",
          "countryCode",
          "status",
          "reviewStatus",
          "useCase",
          "createdAt",
          "billing"
        ],
        "description": "One short code application of the workspace, with its code once one is assigned. Drafts, rejected and cancelled applications are listed too."
      },
      "ShortCodeApplication": {
        "type": "object",
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The application's id. `null` before the first save."
          },
          "shortCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "The assigned code's digits. `null` until Sendly assigns one."
          },
          "countryCode": {
            "type": "string",
            "description": "`US` before the first save."
          },
          "status": {
            "type": "string",
            "description": "Where the code is in provisioning. Only `active` can send. Known values: `requested`, `provisioning`, `parked`, `active`, `suspended`, `cancelled`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "requested",
              "provisioning",
              "parked",
              "active",
              "suspended",
              "cancelled"
            ]
          },
          "reviewStatus": {
            "type": "string",
            "description": "Where Sendly's review of the application stands. Known values: `draft`, `awaiting_review`, `changes_requested`, `approved_for_filing`, `filed`, `rejected`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "awaiting_review",
              "changes_requested",
              "approved_for_filing",
              "filed",
              "rejected"
            ]
          },
          "reviewNote": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sendly's note from the review, such as what to change."
          },
          "orderType": {
            "type": "string",
            "enum": [
              "new",
              "migration"
            ],
            "description": "`new` for a new code, `migration` to move one from another provider."
          },
          "codeType": {
            "type": "string",
            "enum": [
              "random",
              "vanity"
            ],
            "description": "`random` for any available code, `vanity` for chosen digits."
          },
          "contentProviderSameAsBrand": {
            "type": "boolean",
            "description": "Whether the content provider is the brand itself. `true` before the first save."
          },
          "sampleMessages": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Example messages. Empty before the first save."
          },
          "useCase": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the code will be used for."
          },
          "optInFlow": {
            "type": [
              "string",
              "null"
            ],
            "description": "How subscribers opt in."
          },
          "expectedMonthlyVolume": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expected messages a month."
          },
          "expectedDailyVolume": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expected messages a day."
          },
          "helpResponse": {
            "type": [
              "string",
              "null"
            ],
            "description": "The reply to HELP."
          },
          "stopConfirmation": {
            "type": [
              "string",
              "null"
            ],
            "description": "The reply to STOP."
          },
          "optInConfirmation": {
            "type": [
              "string",
              "null"
            ],
            "description": "The message sent when someone opts in."
          },
          "privacyPolicyUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The privacy policy URL."
          },
          "termsUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The terms and conditions URL."
          },
          "messageFrequency": {
            "type": [
              "string",
              "null"
            ],
            "description": "How often subscribers get messages, such as `4 messages per month`."
          },
          "campaignKeyword": {
            "type": [
              "string",
              "null"
            ],
            "description": "The keyword subscribers text to join."
          },
          "requestedDigits": {
            "type": [
              "string",
              "null"
            ],
            "description": "The digits asked for: a vanity code, or the code being migrated."
          },
          "losingProvider": {
            "type": [
              "string",
              "null"
            ],
            "description": "The provider a migrated code is moving from."
          },
          "brandContactName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The brand's contact for the Short Code Registry."
          },
          "brandContactEmail": {
            "type": [
              "string",
              "null"
            ],
            "description": "The brand contact's email."
          },
          "brandContactPhone": {
            "type": [
              "string",
              "null"
            ],
            "description": "The brand contact's phone number."
          },
          "contentProviderLegalName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider's legal name."
          },
          "contentProviderEin": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider's EIN."
          },
          "contentProviderContactName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider's contact."
          },
          "contentProviderContactEmail": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider contact's email."
          },
          "contentProviderContactPhone": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider contact's phone number."
          },
          "brandRegistrationStatus": {
            "type": "string",
            "description": "Where the Short Code Registry registration stands. Known values: `not_started`, `submitted`, `awaiting_email_verification`, `vetting`, `registered`, `rejected`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "not_started",
              "submitted",
              "awaiting_email_verification",
              "vetting",
              "registered",
              "rejected"
            ]
          },
          "contentProviderRegistrationStatus": {
            "type": "string",
            "description": "Where the Short Code Registry registration stands. Known values: `not_started`, `submitted`, `awaiting_email_verification`, `vetting`, `registered`, `rejected`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "not_started",
              "submitted",
              "awaiting_email_verification",
              "vetting",
              "registered",
              "rejected"
            ]
          },
          "submittedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the application was submitted for review. ISO 8601, in UTC."
          },
          "reviewedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When Sendly finished reviewing it. ISO 8601, in UTC."
          },
          "filedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was filed with the carriers. ISO 8601, in UTC."
          },
          "activatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the code went live. ISO 8601, in UTC."
          },
          "registryRevettingDueAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the registry registration is next due to be re-vetted. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the application was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the application last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "shortCode",
          "countryCode",
          "status",
          "reviewStatus",
          "reviewNote",
          "orderType",
          "codeType",
          "contentProviderSameAsBrand",
          "sampleMessages",
          "useCase",
          "optInFlow",
          "expectedMonthlyVolume",
          "expectedDailyVolume",
          "helpResponse",
          "stopConfirmation",
          "optInConfirmation",
          "privacyPolicyUrl",
          "termsUrl",
          "messageFrequency",
          "campaignKeyword",
          "requestedDigits",
          "losingProvider",
          "brandContactName",
          "brandContactEmail",
          "brandContactPhone",
          "contentProviderLegalName",
          "contentProviderEin",
          "contentProviderContactName",
          "contentProviderContactEmail",
          "contentProviderContactPhone",
          "brandRegistrationStatus",
          "contentProviderRegistrationStatus",
          "submittedAt",
          "reviewedAt",
          "filedAt",
          "activatedAt",
          "registryRevettingDueAt",
          "createdAt",
          "updatedAt"
        ],
        "description": "The workspace's short code application. With no application yet, the empty shape: `id` is `null`, the choices show their defaults, and every answer is `null`."
      },
      "ShortCodeApplicationInput": {
        "type": "object",
        "properties": {
          "useCase": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the code will be used for."
          },
          "optInFlow": {
            "type": [
              "string",
              "null"
            ],
            "description": "How subscribers opt in."
          },
          "optInConfirmation": {
            "type": [
              "string",
              "null"
            ],
            "description": "The message sent when someone opts in."
          },
          "helpResponse": {
            "type": [
              "string",
              "null"
            ],
            "description": "The reply to HELP: the program name, a help contact, `Msg&data rates may apply`, the message frequency and how to stop."
          },
          "stopConfirmation": {
            "type": [
              "string",
              "null"
            ],
            "description": "The reply to STOP."
          },
          "messageFrequency": {
            "type": [
              "string",
              "null"
            ],
            "description": "Specific, such as `4 messages per month`, or `Message frequency varies`."
          },
          "campaignKeyword": {
            "type": [
              "string",
              "null"
            ],
            "description": "The join keyword: 2 to 20 letters or numbers, not a reserved word such as STOP or HELP."
          },
          "expectedMonthlyVolume": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expected messages a month."
          },
          "expectedDailyVolume": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expected messages a day."
          },
          "privacyPolicyUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The privacy policy URL."
          },
          "termsUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The terms and conditions URL."
          },
          "countryCode": {
            "type": "string",
            "enum": [
              "US"
            ],
            "description": "Only `US`. Matched ignoring case."
          },
          "orderType": {
            "type": "string",
            "enum": [
              "new",
              "migration"
            ],
            "description": "`new` or `migration`. Matched ignoring case. Any other value answers 422."
          },
          "codeType": {
            "type": "string",
            "enum": [
              "random",
              "vanity"
            ],
            "description": "`random` or `vanity`. Matched ignoring case. Any other value answers 422."
          },
          "requestedDigits": {
            "type": [
              "string",
              "null"
            ],
            "description": "5 or 6 digits: the vanity code, or the code being migrated."
          },
          "losingProvider": {
            "type": [
              "string",
              "null"
            ],
            "description": "For a migration, the provider the code is moving from."
          },
          "brandContactName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The brand's contact for the Short Code Registry."
          },
          "brandContactEmail": {
            "type": [
              "string",
              "null"
            ],
            "description": "The brand contact's email."
          },
          "brandContactPhone": {
            "type": [
              "string",
              "null"
            ],
            "description": "The brand contact's phone number."
          },
          "contentProviderSameAsBrand": {
            "type": "boolean",
            "description": "Whether the content provider is the brand itself."
          },
          "contentProviderLegalName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider's legal name, when it is not the brand."
          },
          "contentProviderEin": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider's EIN."
          },
          "contentProviderContactName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider's contact."
          },
          "contentProviderContactEmail": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider contact's email."
          },
          "contentProviderContactPhone": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content provider contact's phone number."
          },
          "sampleMessages": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Real examples of the messages. `null` clears them."
          }
        },
        "description": "Answers to save on the application. Every field is optional: a field left out keeps its saved value, and `null` or a blank string clears it. Strings are trimmed. Fields Sendly or the carriers own are not saved and are named back in `ignoredFields`."
      },
      "ShortCodeApplicationSaved": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "application": {
            "$ref": "#/components/schemas/ShortCodeApplication"
          },
          "prefill": {
            "$ref": "#/components/schemas/ShortCodePrefill"
          },
          "editable": {
            "type": "boolean",
            "description": "Whether a save can change the application."
          },
          "lockMessage": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the application cannot be edited. `null` while it can."
          },
          "canStartNewApplication": {
            "type": "boolean",
            "description": "Whether the application is finished (rejected or cancelled), so the next save starts a new one."
          },
          "generatedDefaults": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "useCase": {
                "type": "string"
              },
              "optInFlow": {
                "type": "string"
              }
            },
            "description": "Wording Sendly suggested for this application. Submit refuses it until it has been edited. `null` when nothing was suggested."
          },
          "requiredDocuments": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order_brief",
                "brand_registration",
                "content_provider_registration",
                "migration_letter",
                "loa"
              ]
            },
            "description": "The forms this order type needs."
          },
          "missingDocuments": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order_brief",
                "brand_registration",
                "content_provider_registration",
                "migration_letter",
                "loa"
              ]
            },
            "description": "The required forms not signed yet."
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShortCodeDocument"
            },
            "description": "The forms Sendly has prepared for this application."
          },
          "quote": {
            "type": "object",
            "properties": {
              "codeType": {
                "type": "string",
                "enum": [
                  "random",
                  "vanity"
                ],
                "description": "`random` for any available code, `vanity` for chosen digits."
              },
              "monthlyUsd": {
                "type": "integer",
                "description": "The monthly lease, in US dollars."
              },
              "setupUsd": {
                "type": "integer",
                "description": "The one-time setup fee, in US dollars."
              },
              "currency": {
                "type": "string",
                "enum": [
                  "USD"
                ]
              },
              "autoBilled": {
                "type": "boolean",
                "enum": [
                  false
                ],
                "description": "Always `false`, kept for older clients: `billing` says what is charged and when."
              },
              "setupCents": {
                "type": "integer",
                "description": "The one-time setup fee, in US cents."
              },
              "monthlyCents": {
                "type": "integer",
                "description": "The monthly lease, in US cents."
              },
              "minimumTermMonths": {
                "type": "integer",
                "description": "The minimum lease term, in months."
              },
              "setupChargedAt": {
                "type": "string",
                "enum": [
                  "submit"
                ]
              },
              "leaseStartsAt": {
                "type": "string",
                "enum": [
                  "go_live"
                ]
              }
            },
            "required": [
              "codeType",
              "monthlyUsd",
              "setupUsd",
              "currency",
              "autoBilled",
              "setupCents",
              "monthlyCents",
              "minimumTermMonths",
              "setupChargedAt",
              "leaseStartsAt"
            ],
            "description": "The price: the published one for this code type, or once submitted the one fixed at submit."
          },
          "billing": {
            "$ref": "#/components/schemas/ShortCodeBilling"
          },
          "verification": {
            "type": "object",
            "properties": {
              "verified": {
                "type": "boolean"
              },
              "state": {
                "type": "string",
                "enum": [
                  "verified",
                  "in_review",
                  "needs_attention",
                  "not_started"
                ]
              },
              "href": {
                "type": "string",
                "description": "The dashboard page for the verification."
              }
            },
            "required": [
              "verified",
              "state",
              "href"
            ],
            "description": "Whether the business is verified, which submitting needs."
          },
          "carriers": {
            "type": "object",
            "properties": {
              "approved": {
                "type": "integer",
                "description": "How many carriers have approved the code."
              },
              "total": {
                "type": "integer",
                "description": "How many carriers certify it."
              },
              "overall": {
                "type": "string",
                "enum": [
                  "not_submitted",
                  "in_progress",
                  "approved",
                  "rejected"
                ]
              },
              "byCarrier": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "carrier": {
                      "type": "string",
                      "enum": [
                        "ATT",
                        "TMOBILE",
                        "VERIZON",
                        "US_CELLULAR"
                      ],
                      "description": "The carrier. Every carrier that certifies the code is listed, one entry each, always these four."
                    },
                    "label": {
                      "type": "string",
                      "description": "The carrier's name, such as `T-Mobile`."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "not_submitted",
                        "submitted",
                        "in_review",
                        "approved",
                        "rejected"
                      ],
                      "description": "The carrier's certification of the code, as Sendly last recorded it. These are Sendly's own states, not the carrier's: `not_submitted` until Sendly records one, and any other recorded value is sent as `not_submitted`."
                    },
                    "updatedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "When the carrier's status was last recorded, as recorded."
                    }
                  },
                  "required": [
                    "carrier",
                    "label",
                    "status",
                    "updatedAt"
                  ]
                }
              }
            },
            "required": [
              "approved",
              "total",
              "overall",
              "byCarrier"
            ],
            "description": "Where each carrier's certification stands."
          },
          "ignoredFields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fields the body sent that Sendly or the carriers own, such as `status` or `short_code`, which were not saved. Absent when there were none. Unknown fields are dropped without being named."
          }
        },
        "required": [
          "enabled",
          "application",
          "prefill",
          "editable",
          "lockMessage",
          "canStartNewApplication",
          "generatedDefaults",
          "requiredDocuments",
          "missingDocuments",
          "documents",
          "quote",
          "billing",
          "verification",
          "carriers"
        ],
        "description": "The application as saved, with the fields that were not saved."
      },
      "ShortCodeApplicationSubmitted": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "application": {
            "$ref": "#/components/schemas/ShortCodeApplication"
          },
          "prefill": {
            "$ref": "#/components/schemas/ShortCodePrefill"
          },
          "editable": {
            "type": "boolean",
            "description": "Whether a save can change the application."
          },
          "lockMessage": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the application cannot be edited. `null` while it can."
          },
          "canStartNewApplication": {
            "type": "boolean",
            "description": "Whether the application is finished (rejected or cancelled), so the next save starts a new one."
          },
          "generatedDefaults": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "useCase": {
                "type": "string"
              },
              "optInFlow": {
                "type": "string"
              }
            },
            "description": "Wording Sendly suggested for this application. Submit refuses it until it has been edited. `null` when nothing was suggested."
          },
          "requiredDocuments": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order_brief",
                "brand_registration",
                "content_provider_registration",
                "migration_letter",
                "loa"
              ]
            },
            "description": "The forms this order type needs."
          },
          "missingDocuments": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order_brief",
                "brand_registration",
                "content_provider_registration",
                "migration_letter",
                "loa"
              ]
            },
            "description": "The required forms not signed yet."
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShortCodeDocument"
            },
            "description": "The forms Sendly has prepared for this application."
          },
          "quote": {
            "type": "object",
            "properties": {
              "codeType": {
                "type": "string",
                "enum": [
                  "random",
                  "vanity"
                ],
                "description": "`random` for any available code, `vanity` for chosen digits."
              },
              "monthlyUsd": {
                "type": "integer",
                "description": "The monthly lease, in US dollars."
              },
              "setupUsd": {
                "type": "integer",
                "description": "The one-time setup fee, in US dollars."
              },
              "currency": {
                "type": "string",
                "enum": [
                  "USD"
                ]
              },
              "autoBilled": {
                "type": "boolean",
                "enum": [
                  false
                ],
                "description": "Always `false`, kept for older clients: `billing` says what is charged and when."
              },
              "setupCents": {
                "type": "integer",
                "description": "The one-time setup fee, in US cents."
              },
              "monthlyCents": {
                "type": "integer",
                "description": "The monthly lease, in US cents."
              },
              "minimumTermMonths": {
                "type": "integer",
                "description": "The minimum lease term, in months."
              },
              "setupChargedAt": {
                "type": "string",
                "enum": [
                  "submit"
                ]
              },
              "leaseStartsAt": {
                "type": "string",
                "enum": [
                  "go_live"
                ]
              }
            },
            "required": [
              "codeType",
              "monthlyUsd",
              "setupUsd",
              "currency",
              "autoBilled",
              "setupCents",
              "monthlyCents",
              "minimumTermMonths",
              "setupChargedAt",
              "leaseStartsAt"
            ],
            "description": "The price: the published one for this code type, or once submitted the one fixed at submit."
          },
          "billing": {
            "$ref": "#/components/schemas/ShortCodeBilling"
          },
          "verification": {
            "type": "object",
            "properties": {
              "verified": {
                "type": "boolean"
              },
              "state": {
                "type": "string",
                "enum": [
                  "verified",
                  "in_review",
                  "needs_attention",
                  "not_started"
                ]
              },
              "href": {
                "type": "string",
                "description": "The dashboard page for the verification."
              }
            },
            "required": [
              "verified",
              "state",
              "href"
            ],
            "description": "Whether the business is verified, which submitting needs."
          },
          "carriers": {
            "type": "object",
            "properties": {
              "approved": {
                "type": "integer",
                "description": "How many carriers have approved the code."
              },
              "total": {
                "type": "integer",
                "description": "How many carriers certify it."
              },
              "overall": {
                "type": "string",
                "enum": [
                  "not_submitted",
                  "in_progress",
                  "approved",
                  "rejected"
                ]
              },
              "byCarrier": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "carrier": {
                      "type": "string",
                      "enum": [
                        "ATT",
                        "TMOBILE",
                        "VERIZON",
                        "US_CELLULAR"
                      ],
                      "description": "The carrier. Every carrier that certifies the code is listed, one entry each, always these four."
                    },
                    "label": {
                      "type": "string",
                      "description": "The carrier's name, such as `T-Mobile`."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "not_submitted",
                        "submitted",
                        "in_review",
                        "approved",
                        "rejected"
                      ],
                      "description": "The carrier's certification of the code, as Sendly last recorded it. These are Sendly's own states, not the carrier's: `not_submitted` until Sendly records one, and any other recorded value is sent as `not_submitted`."
                    },
                    "updatedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "When the carrier's status was last recorded, as recorded."
                    }
                  },
                  "required": [
                    "carrier",
                    "label",
                    "status",
                    "updatedAt"
                  ]
                }
              }
            },
            "required": [
              "approved",
              "total",
              "overall",
              "byCarrier"
            ],
            "description": "Where each carrier's certification stands."
          },
          "submitted": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "alreadySubmitted": {
            "type": "boolean",
            "description": "`true` when the application was already with Sendly for review, so nothing changed."
          },
          "notified": {
            "type": "boolean",
            "description": "Whether Sendly's review team was told. `false` when it was already submitted, or the notice failed."
          },
          "payment": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "description": "Where the one-time setup fee stands. `unpaid` until a submit charges it; `paid` and `waived` let Sendly file the application. Known values: `unpaid`, `processing`, `requires_action`, `failed`, `no_payment_method`, `paid`, `waived`, `refund_pending`, `refunded`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "unpaid",
                  "processing",
                  "requires_action",
                  "failed",
                  "no_payment_method",
                  "paid",
                  "waived",
                  "refund_pending",
                  "refunded"
                ]
              },
              "charged": {
                "type": "boolean",
                "description": "Whether this call charged the card."
              }
            },
            "required": [
              "status",
              "charged"
            ],
            "description": "The setup fee, when this call collected it. Absent when the application was already in review before the call."
          }
        },
        "required": [
          "enabled",
          "application",
          "prefill",
          "editable",
          "lockMessage",
          "canStartNewApplication",
          "generatedDefaults",
          "requiredDocuments",
          "missingDocuments",
          "documents",
          "quote",
          "billing",
          "verification",
          "carriers",
          "submitted",
          "alreadySubmitted",
          "notified"
        ],
        "description": "The application, now with Sendly for review."
      },
      "ShortCodeApplicationView": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "application": {
            "$ref": "#/components/schemas/ShortCodeApplication"
          },
          "prefill": {
            "$ref": "#/components/schemas/ShortCodePrefill"
          },
          "editable": {
            "type": "boolean",
            "description": "Whether a save can change the application."
          },
          "lockMessage": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the application cannot be edited. `null` while it can."
          },
          "canStartNewApplication": {
            "type": "boolean",
            "description": "Whether the application is finished (rejected or cancelled), so the next save starts a new one."
          },
          "generatedDefaults": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "useCase": {
                "type": "string"
              },
              "optInFlow": {
                "type": "string"
              }
            },
            "description": "Wording Sendly suggested for this application. Submit refuses it until it has been edited. `null` when nothing was suggested."
          },
          "requiredDocuments": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order_brief",
                "brand_registration",
                "content_provider_registration",
                "migration_letter",
                "loa"
              ]
            },
            "description": "The forms this order type needs."
          },
          "missingDocuments": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order_brief",
                "brand_registration",
                "content_provider_registration",
                "migration_letter",
                "loa"
              ]
            },
            "description": "The required forms not signed yet."
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShortCodeDocument"
            },
            "description": "The forms Sendly has prepared for this application."
          },
          "quote": {
            "type": "object",
            "properties": {
              "codeType": {
                "type": "string",
                "enum": [
                  "random",
                  "vanity"
                ],
                "description": "`random` for any available code, `vanity` for chosen digits."
              },
              "monthlyUsd": {
                "type": "integer",
                "description": "The monthly lease, in US dollars."
              },
              "setupUsd": {
                "type": "integer",
                "description": "The one-time setup fee, in US dollars."
              },
              "currency": {
                "type": "string",
                "enum": [
                  "USD"
                ]
              },
              "autoBilled": {
                "type": "boolean",
                "enum": [
                  false
                ],
                "description": "Always `false`, kept for older clients: `billing` says what is charged and when."
              },
              "setupCents": {
                "type": "integer",
                "description": "The one-time setup fee, in US cents."
              },
              "monthlyCents": {
                "type": "integer",
                "description": "The monthly lease, in US cents."
              },
              "minimumTermMonths": {
                "type": "integer",
                "description": "The minimum lease term, in months."
              },
              "setupChargedAt": {
                "type": "string",
                "enum": [
                  "submit"
                ]
              },
              "leaseStartsAt": {
                "type": "string",
                "enum": [
                  "go_live"
                ]
              }
            },
            "required": [
              "codeType",
              "monthlyUsd",
              "setupUsd",
              "currency",
              "autoBilled",
              "setupCents",
              "monthlyCents",
              "minimumTermMonths",
              "setupChargedAt",
              "leaseStartsAt"
            ],
            "description": "The price: the published one for this code type, or once submitted the one fixed at submit."
          },
          "billing": {
            "$ref": "#/components/schemas/ShortCodeBilling"
          },
          "verification": {
            "type": "object",
            "properties": {
              "verified": {
                "type": "boolean"
              },
              "state": {
                "type": "string",
                "enum": [
                  "verified",
                  "in_review",
                  "needs_attention",
                  "not_started"
                ]
              },
              "href": {
                "type": "string",
                "description": "The dashboard page for the verification."
              }
            },
            "required": [
              "verified",
              "state",
              "href"
            ],
            "description": "Whether the business is verified, which submitting needs."
          },
          "carriers": {
            "type": "object",
            "properties": {
              "approved": {
                "type": "integer",
                "description": "How many carriers have approved the code."
              },
              "total": {
                "type": "integer",
                "description": "How many carriers certify it."
              },
              "overall": {
                "type": "string",
                "enum": [
                  "not_submitted",
                  "in_progress",
                  "approved",
                  "rejected"
                ]
              },
              "byCarrier": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "carrier": {
                      "type": "string",
                      "enum": [
                        "ATT",
                        "TMOBILE",
                        "VERIZON",
                        "US_CELLULAR"
                      ],
                      "description": "The carrier. Every carrier that certifies the code is listed, one entry each, always these four."
                    },
                    "label": {
                      "type": "string",
                      "description": "The carrier's name, such as `T-Mobile`."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "not_submitted",
                        "submitted",
                        "in_review",
                        "approved",
                        "rejected"
                      ],
                      "description": "The carrier's certification of the code, as Sendly last recorded it. These are Sendly's own states, not the carrier's: `not_submitted` until Sendly records one, and any other recorded value is sent as `not_submitted`."
                    },
                    "updatedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "When the carrier's status was last recorded, as recorded."
                    }
                  },
                  "required": [
                    "carrier",
                    "label",
                    "status",
                    "updatedAt"
                  ]
                }
              }
            },
            "required": [
              "approved",
              "total",
              "overall",
              "byCarrier"
            ],
            "description": "Where each carrier's certification stands."
          }
        },
        "required": [
          "enabled",
          "application",
          "prefill",
          "editable",
          "lockMessage",
          "canStartNewApplication",
          "generatedDefaults",
          "requiredDocuments",
          "missingDocuments",
          "documents",
          "quote",
          "billing",
          "verification",
          "carriers"
        ],
        "description": "The application, with everything needed to act on it."
      },
      "ShortCodeBilling": {
        "type": "object",
        "properties": {
          "setupFee": {
            "type": "object",
            "properties": {
              "amountCents": {
                "type": "integer",
                "description": "The setup fee, in US cents."
              },
              "status": {
                "type": "string",
                "description": "Where the one-time setup fee stands. `unpaid` until a submit charges it; `paid` and `waived` let Sendly file the application. Known values: `unpaid`, `processing`, `requires_action`, `failed`, `no_payment_method`, `paid`, `waived`, `refund_pending`, `refunded`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "unpaid",
                  "processing",
                  "requires_action",
                  "failed",
                  "no_payment_method",
                  "paid",
                  "waived",
                  "refund_pending",
                  "refunded"
                ]
              },
              "chargedAt": {
                "type": "string",
                "enum": [
                  "submit"
                ],
                "description": "The fee is charged at submit."
              },
              "paidAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the fee was paid. ISO 8601, in UTC."
              },
              "refundedCents": {
                "type": "integer"
              },
              "refundedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the fee was refunded. ISO 8601, in UTC."
              }
            },
            "required": [
              "amountCents",
              "status",
              "chargedAt",
              "paidAt",
              "refundedCents",
              "refundedAt"
            ]
          },
          "lease": {
            "type": "object",
            "properties": {
              "monthlyCents": {
                "type": "integer",
                "description": "The monthly lease, in US cents."
              },
              "minimumTermMonths": {
                "type": "integer",
                "description": "The minimum lease term, in months: 3 unless agreed otherwise."
              },
              "state": {
                "type": "string",
                "description": "Where the monthly lease stands. It starts when the code goes live. Known values: `not_started`, `running`, `past_due`, `paused`, `ending`, `ended`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "not_started",
                  "running",
                  "past_due",
                  "paused",
                  "ending",
                  "ended"
                ]
              },
              "billingEnabled": {
                "type": "boolean",
                "description": "Whether Sendly bills the lease yet."
              },
              "startedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the lease started: when the code went live. ISO 8601, in UTC."
              },
              "nextChargeAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the next month is charged. `null` when nothing more is billed. ISO 8601, in UTC."
              },
              "paidThrough": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "The end of the last month paid for, or waived. ISO 8601, in UTC."
              },
              "termEndsAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the minimum term ends. ISO 8601, in UTC."
              },
              "endsAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When a cancelled lease ends. ISO 8601, in UTC."
              },
              "cancelRequestedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the lease was cancelled. ISO 8601, in UTC."
              },
              "pastDue": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/ShortCodeLeasePastDue"
                  },
                  {
                    "type": "null"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "`null` when nothing is unpaid."
              },
              "dueMonths": {
                "type": "integer",
                "description": "Months used but not yet charged."
              },
              "dueCents": {
                "type": "integer",
                "description": "What those months cost, in US cents."
              },
              "startsAt": {
                "type": "string",
                "enum": [
                  "go_live"
                ],
                "description": "The lease starts when the code goes live."
              }
            },
            "required": [
              "monthlyCents",
              "minimumTermMonths",
              "state",
              "billingEnabled",
              "startedAt",
              "nextChargeAt",
              "paidThrough",
              "termEndsAt",
              "endsAt",
              "cancelRequestedAt",
              "pastDue",
              "dueMonths",
              "dueCents",
              "startsAt"
            ]
          },
          "terms": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string",
                "enum": [
                  "2026-10-06"
                ],
                "description": "The current terms."
              },
              "acceptedVersion": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The terms accepted at submit."
              },
              "acceptedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the terms were accepted. ISO 8601, in UTC."
              }
            },
            "required": [
              "version",
              "acceptedVersion",
              "acceptedAt"
            ]
          },
          "refundPolicy": {
            "type": "string",
            "enum": [
              "full_refund_before_filing"
            ],
            "description": "The setup fee is refunded in full if the application is rejected or cancelled before filing."
          },
          "exempt": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "mock",
              "enterprise",
              null
            ],
            "description": "Why the workspace pays no fee, if it does not: a test account, or an enterprise invoiced separately."
          },
          "charges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShortCodeCharge"
            },
            "description": "The application's charges."
          }
        },
        "required": [
          "setupFee",
          "lease",
          "terms",
          "refundPolicy",
          "exempt",
          "charges"
        ],
        "description": "The application's setup fee, lease and terms."
      },
      "ShortCodeCharge": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The charge's id."
          },
          "kind": {
            "type": "string",
            "description": "What the charge is for. Known values: `setup`, `lease`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "setup",
              "lease"
            ]
          },
          "amountCents": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "description": "Where the charge stands, such as `paid`, `processing`, `failed`, `waived`, `refunded`, or `not_charged` for a lease month that was never billed."
          },
          "paidAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was paid. ISO 8601, in UTC."
          },
          "refundedCents": {
            "type": "integer"
          },
          "refundedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When it was refunded. ISO 8601, in UTC."
          },
          "periodStart": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "For a lease charge, the start of the month it pays for. ISO 8601, in UTC."
          },
          "periodEnd": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "For a lease charge, the end of the month it pays for. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the charge was recorded. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "kind",
          "amountCents",
          "status",
          "paidAt",
          "refundedCents",
          "refundedAt",
          "periodStart",
          "periodEnd",
          "createdAt"
        ]
      },
      "ShortCodeDocument": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "description": "The carrier form. Known values: `order_brief`, `brand_registration`, `content_provider_registration`, `migration_letter`, `loa`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "order_brief",
              "brand_registration",
              "content_provider_registration",
              "migration_letter",
              "loa"
            ]
          },
          "templateReady": {
            "type": "boolean",
            "description": "Whether Sendly has prepared the form for signing."
          },
          "signedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the form was signed. ISO 8601, in UTC."
          },
          "signedByName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Who signed it."
          },
          "awaitingSignature": {
            "type": "boolean",
            "description": "Whether a signing link is out and has not expired."
          }
        },
        "required": [
          "kind",
          "templateReady",
          "signedAt",
          "signedByName",
          "awaitingSignature"
        ],
        "description": "A carrier form the application needs."
      },
      "ShortCodeInternalError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "short_code_internal_error"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "short_code_internal_error",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "short_code_internal_error"
        ]
      },
      "ShortCodeIssue": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "description": "The field the issue is about, such as `helpResponse` or `documents.loa`."
          },
          "message": {
            "type": "string",
            "description": "What to change, for people."
          }
        },
        "required": [
          "path",
          "message"
        ],
        "description": "A compliance problem with the application, by field."
      },
      "ShortCodeLeasePastDue": {
        "type": "object",
        "properties": {
          "chargeId": {
            "type": "string",
            "description": "The unpaid lease charge."
          },
          "amountCents": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "description": "The charge's status, `paid` for a charged one."
          },
          "periodStart": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The start of the month it pays for. ISO 8601, in UTC."
          },
          "periodEnd": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The end of the month it pays for. ISO 8601, in UTC."
          },
          "firstFailedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When charging it first failed. ISO 8601, in UTC."
          },
          "pauseAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the code is paused for non-payment if it is still unpaid. ISO 8601, in UTC."
          },
          "noticeStage": {
            "type": [
              "string",
              "null"
            ],
            "description": "The last payment notice sent."
          }
        },
        "required": [
          "chargeId",
          "amountCents",
          "status",
          "periodStart",
          "periodEnd",
          "firstFailedAt",
          "pauseAt",
          "noticeStage"
        ],
        "description": "The oldest unpaid lease charge."
      },
      "ShortCodeList": {
        "type": "object",
        "properties": {
          "shortCodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShortCode"
            }
          }
        },
        "required": [
          "shortCodes"
        ]
      },
      "ShortCodeListBilling": {
        "type": "object",
        "properties": {
          "setupFee": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "description": "Where the one-time setup fee stands. `unpaid` until a submit charges it; `paid` and `waived` let Sendly file the application. Known values: `unpaid`, `processing`, `requires_action`, `failed`, `no_payment_method`, `paid`, `waived`, `refund_pending`, `refunded`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "unpaid",
                  "processing",
                  "requires_action",
                  "failed",
                  "no_payment_method",
                  "paid",
                  "waived",
                  "refund_pending",
                  "refunded"
                ]
              },
              "amountCents": {
                "type": "integer"
              }
            },
            "required": [
              "status",
              "amountCents"
            ]
          },
          "lease": {
            "type": "object",
            "properties": {
              "monthlyCents": {
                "type": "integer",
                "description": "The monthly lease, in US cents."
              },
              "minimumTermMonths": {
                "type": "integer",
                "description": "The minimum lease term, in months: 3 unless agreed otherwise."
              },
              "state": {
                "type": "string",
                "description": "Where the monthly lease stands. It starts when the code goes live. Known values: `not_started`, `running`, `past_due`, `paused`, `ending`, `ended`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "not_started",
                  "running",
                  "past_due",
                  "paused",
                  "ending",
                  "ended"
                ]
              },
              "billingEnabled": {
                "type": "boolean",
                "description": "Whether Sendly bills the lease yet."
              },
              "startedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the lease started: when the code went live. ISO 8601, in UTC."
              },
              "nextChargeAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the next month is charged. `null` when nothing more is billed. ISO 8601, in UTC."
              },
              "paidThrough": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "The end of the last month paid for, or waived. ISO 8601, in UTC."
              },
              "termEndsAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the minimum term ends. ISO 8601, in UTC."
              },
              "endsAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When a cancelled lease ends. ISO 8601, in UTC."
              },
              "cancelRequestedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the lease was cancelled. ISO 8601, in UTC."
              },
              "pastDue": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/ShortCodeLeasePastDue"
                  },
                  {
                    "type": "null"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "`null` when nothing is unpaid."
              },
              "dueMonths": {
                "type": "integer",
                "description": "Months used but not yet charged."
              },
              "dueCents": {
                "type": "integer",
                "description": "What those months cost, in US cents."
              }
            },
            "required": [
              "monthlyCents",
              "minimumTermMonths",
              "state",
              "billingEnabled",
              "startedAt",
              "nextChargeAt",
              "paidThrough",
              "termEndsAt",
              "endsAt",
              "cancelRequestedAt",
              "pastDue",
              "dueMonths",
              "dueCents"
            ]
          }
        },
        "required": [
          "setupFee",
          "lease"
        ],
        "description": "The code's setup fee and lease."
      },
      "ShortCodePrefill": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "tendlc",
              "verification",
              "none"
            ],
            "description": "Where the suggestions come from: the workspace's 10DLC brand, its toll-free verification, or neither."
          },
          "legalName": {
            "type": "string",
            "description": "The business's legal name."
          },
          "dba": {
            "type": "string",
            "description": "The name the business trades as."
          },
          "ein": {
            "type": "string",
            "description": "The business's EIN."
          },
          "websiteUrl": {
            "type": "string",
            "description": "The business's website."
          },
          "address": {
            "type": "object",
            "properties": {
              "line1": {
                "type": "string"
              },
              "line2": {
                "type": "string"
              },
              "city": {
                "type": "string"
              },
              "state": {
                "type": "string"
              },
              "postalCode": {
                "type": "string"
              },
              "countryCode": {
                "type": "string"
              }
            },
            "description": "The business address. Only the parts that are known."
          },
          "contact": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "email": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              }
            },
            "description": "The business contact. Only the parts that are known."
          },
          "privacyPolicyUrl": {
            "type": "string",
            "description": "The privacy policy URL from the toll-free verification."
          },
          "termsUrl": {
            "type": "string",
            "description": "The terms URL from the toll-free verification."
          },
          "usesHostedLegalPages": {
            "type": "boolean",
            "description": "Whether the toll-free verification uses Sendly's hosted legal pages."
          }
        },
        "required": [
          "source"
        ],
        "description": "Suggestions from what the workspace has already told Sendly. Never saved on the application unless sent back with a save. Fields with no value are left out."
      },
      "ShortCodePreflight": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "Whether the application can be submitted as it is."
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShortCodeIssue"
            },
            "description": "Every issue found, all at once."
          },
          "requiredDocuments": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order_brief",
                "brand_registration",
                "content_provider_registration",
                "migration_letter",
                "loa"
              ]
            },
            "description": "The forms this order type needs."
          },
          "missingDocuments": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order_brief",
                "brand_registration",
                "content_provider_registration",
                "migration_letter",
                "loa"
              ]
            },
            "description": "The required forms not signed yet."
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShortCodeDocument"
            },
            "description": "The forms Sendly has prepared for this application."
          },
          "ignoredFields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fields the body sent that Sendly or the carriers own, such as `status` or `short_code`, which were not saved. Absent when there were none. Unknown fields are dropped without being named."
          }
        },
        "required": [
          "ok",
          "issues",
          "requiredDocuments",
          "missingDocuments",
          "documents"
        ],
        "description": "A dry run of submitting the application. Nothing is saved."
      },
      "ShortCodeRequestCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The new application's id."
          },
          "shortCode": {
            "type": "null",
            "description": "Always `null`: Sendly assigns the code later."
          },
          "countryCode": {
            "type": "string",
            "enum": [
              "US"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "requested"
            ]
          },
          "useCase": {
            "type": "string",
            "description": "The use case, trimmed."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the application was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "shortCode",
          "countryCode",
          "status",
          "useCase",
          "createdAt"
        ],
        "description": "The application this request started."
      },
      "ShortCodeRequestInput": {
        "type": "object",
        "properties": {
          "useCase": {
            "type": "string",
            "pattern": "\\S",
            "description": "What the code will be used for. Required, and not blank."
          },
          "optInFlow": {
            "type": "string",
            "pattern": "\\S",
            "description": "How subscribers opt in. Required, and not blank."
          },
          "sampleMessages": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Example messages. Blank entries are dropped."
          },
          "expectedMonthlyVolume": {
            "type": "string"
          },
          "helpResponse": {
            "type": "string",
            "description": "The reply to HELP."
          },
          "stopConfirmation": {
            "type": "string",
            "description": "The reply to STOP."
          }
        },
        "required": [
          "useCase",
          "optInFlow"
        ]
      },
      "ShortCodeSendResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "from": {
            "type": "string",
            "description": "The short code."
          },
          "text": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "sent"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "outbound"
            ]
          },
          "segments": {
            "type": "integer"
          },
          "creditsUsed": {
            "type": "integer"
          },
          "shortCode": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was created. ISO 8601, in UTC."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The stored metadata, which includes `shortCode: true`."
          },
          "message_format": {
            "type": "string",
            "enum": [
              "mms"
            ]
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "URLs of the media sent with the message."
          },
          "messageFormat": {
            "type": "string",
            "enum": [
              "mms"
            ]
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "URLs of the media sent with the message."
          }
        },
        "required": [
          "id",
          "to",
          "from",
          "text",
          "status",
          "direction",
          "segments",
          "creditsUsed",
          "shortCode",
          "createdAt",
          "metadata"
        ],
        "title": "Short code message sent",
        "x-sendly-visibility": "preview"
      },
      "ShortCodesNotEnabledError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "short_codes_not_enabled"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "short_codes_not_enabled",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "short_codes_not_enabled"
        ]
      },
      "ShortLink": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "The link's code, from an alphabet without look-alikes (no `0`, `O`, `1`, `l` or `I`): nine characters for a new link, such as `Ab3xY7kQ9`, and six for a link minted before October 2026, such as `Ab3xY7`, which keeps working."
          },
          "shortUrl": {
            "type": "string",
            "description": "The full short URL to share: the short link domain, then the workspace's brand slug when it has one, then the code, such as `https://sendly.live/l/Ab3xY7` or `https://sendly.live/l/acme/Ab3xY7`."
          },
          "destinationUrl": {
            "type": "string",
            "description": "Where the link redirects, exactly as the redirect sends it: the URL as sent, trimmed, in its WHATWG serialisation, so the scheme and host are lower case, an international host is in its `xn--` form, a bare host gains a trailing `/`, and characters a URL cannot hold are percent-encoded. `HTTPS://Shop.Example.com` becomes `https://shop.example.com/`."
          }
        },
        "required": [
          "code",
          "shortUrl",
          "destinationUrl"
        ],
        "description": "A short link, as `POST /api/v1/links` mints it.",
        "x-sendly-visibility": "preview"
      },
      "ShortLinkDisabled": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "The link's code, from an alphabet without look-alikes (no `0`, `O`, `1`, `l` or `I`): nine characters for a new link, such as `Ab3xY7kQ9`, and six for a link minted before October 2026, such as `Ab3xY7`, which keeps working."
          },
          "disabled": {
            "type": "boolean",
            "description": "The link's state after the change."
          }
        },
        "required": [
          "code",
          "disabled"
        ],
        "description": "A short link's code and its new state.",
        "x-sendly-visibility": "preview"
      },
      "ShortLinkInvalidUrlError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_url"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "invalid_url",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "invalid_url"
        ]
      },
      "ShortLinkList": {
        "type": "object",
        "properties": {
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShortLinkListItem"
            }
          },
          "total": {
            "type": "integer",
            "description": "How many items match, across every page."
          }
        },
        "required": [
          "links",
          "total"
        ],
        "x-sendly-visibility": "preview"
      },
      "ShortLinkListItem": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "The link's code, from an alphabet without look-alikes (no `0`, `O`, `1`, `l` or `I`): nine characters for a new link, such as `Ab3xY7kQ9`, and six for a link minted before October 2026, such as `Ab3xY7`, which keeps working."
          },
          "shortUrl": {
            "type": "string",
            "description": "The full short URL to share: the short link domain, then the brand slug the link was minted with when it has one, then the code, such as `https://sendly.live/l/Ab3xY7` or `https://sendly.live/l/acme/Ab3xY7`."
          },
          "destinationUrl": {
            "type": "string",
            "description": "Where the link redirects. For a link minted from October 2026, the WHATWG serialisation of the URL as sent (or as it appeared in the message, without trailing `.`, `,`, `;`, `:`, `!` or `?`): lower-case scheme and host, an international host in its `xn--` form, a bare host with a trailing `/`. A link minted before then shows the URL as it was stored."
          },
          "brandSlug": {
            "type": [
              "string",
              "null"
            ],
            "description": "The brand slug the link was minted with, or `null` for an unbranded link. Fixed when the link is minted: changing the workspace's slug later does not change it."
          },
          "clickCount": {
            "type": "integer",
            "description": "How many clicks were recorded. Link-preview crawlers are not counted."
          },
          "disabled": {
            "type": "boolean",
            "description": "Whether the link is switched off, by the workspace or by Sendly, so its redirect answers 410."
          },
          "lastCountry": {
            "type": [
              "string",
              "null"
            ],
            "description": "The country code of the newest click, as the edge reported it, or `null` when there is none or it was not known."
          },
          "lastClickedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the link was last clicked. ISO 8601, in UTC."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the link was minted. ISO 8601, in UTC."
          },
          "spark": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Clicks per day for the last 14 days, oldest first: the last entry counts the 24 hours up to now, each earlier entry the 24 hours before it."
          }
        },
        "required": [
          "code",
          "shortUrl",
          "destinationUrl",
          "brandSlug",
          "clickCount",
          "disabled",
          "lastCountry",
          "lastClickedAt",
          "createdAt",
          "spark"
        ],
        "description": "A short link with its clicks, as `GET /api/v1/links` lists it.",
        "x-sendly-visibility": "preview"
      },
      "SmsPricingTier": {
        "type": "object",
        "properties": {
          "credits": {
            "type": "integer",
            "description": "Credits one SMS segment in this tier costs at the standard rate."
          },
          "price_usd": {
            "type": "number",
            "description": "What one SMS segment in this tier costs at the standard rate, in US dollars."
          },
          "description": {
            "type": "string",
            "description": "A label for the tier, such as `US & Canada` or `14 countries`. Fixed text: it does not count `countries`."
          }
        },
        "required": [
          "credits",
          "price_usd",
          "description"
        ]
      },
      "SmsPricingTiers": {
        "type": "object",
        "properties": {
          "domestic": {
            "$ref": "#/components/schemas/SmsPricingTier"
          },
          "tier1": {
            "$ref": "#/components/schemas/SmsPricingTier"
          },
          "tier2": {
            "$ref": "#/components/schemas/SmsPricingTier"
          },
          "tier3": {
            "$ref": "#/components/schemas/SmsPricingTier"
          },
          "tier4": {
            "$ref": "#/components/schemas/SmsPricingTier"
          },
          "tier5": {
            "$ref": "#/components/schemas/SmsPricingTier"
          }
        },
        "required": [
          "domestic",
          "tier1",
          "tier2",
          "tier3",
          "tier4",
          "tier5"
        ],
        "description": "Every price tier, by its name."
      },
      "SmsSendResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "from": {
            "type": "string",
            "description": "The sender. `SENDLY-TEST` on a simulated send."
          },
          "text": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "The status when the message was created: `queued` for a live send, `delivered` or `failed` for a simulated one. Known values are those of `Message.status`. A live send the carrier refused at once still says `queued` here, while the stored message is already `failed` (or `retrying`, when it is retried): read the message for its real status.",
            "x-sendly-extensible-enum": [
              "queued",
              "sent",
              "delivered",
              "read",
              "failed",
              "bounced",
              "retrying",
              "received",
              "partial"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "outbound"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "The simulated error, for a test send to a failure sandbox number. `null` on a live send, even one the carrier refused at once."
          },
          "segments": {
            "type": "integer"
          },
          "creditsUsed": {
            "type": "integer",
            "description": "Credits charged when the message was created. 0 for a simulated send. On a live send it is the quoted amount, even when the carrier refused the message at once and the credits were refunded."
          },
          "senderType": {
            "type": "string",
            "description": "How the sender was chosen. Absent on a simulated send. Known values: `number_pool`, `alphanumeric`, `explicit`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "number_pool",
              "alphanumeric",
              "explicit"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was created. ISO 8601, in UTC."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The custom metadata stored with the message, as sent."
          },
          "message_format": {
            "type": "string",
            "enum": [
              "mms"
            ],
            "description": "Present only for an MMS."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Present only for an MMS."
          },
          "messageFormat": {
            "type": "string",
            "enum": [
              "mms"
            ],
            "description": "Same as `message_format`."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Same as `media_urls`."
          },
          "simulated": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Present when the message was simulated and never reached a handset."
          },
          "simulatedReason": {
            "type": "string",
            "description": "Why a live key's send was simulated: the account is not set up to send to this destination yet."
          },
          "actionUrl": {
            "type": "string",
            "enum": [
              "/verify"
            ],
            "description": "Where to finish setting up, next to `simulatedReason`."
          },
          "warning": {
            "type": "string",
            "description": "Why the `from` you sent was not used."
          },
          "senderNote": {
            "type": "string",
            "description": "How the number pool picks the sender."
          }
        },
        "required": [
          "id",
          "to",
          "from",
          "text",
          "status",
          "direction",
          "error",
          "segments",
          "creditsUsed",
          "createdAt",
          "metadata"
        ],
        "title": "SMS or MMS sent"
      },
      "StartWhatsAppSignupRequest": {
        "type": "object",
        "properties": {
          "phoneNumber": {
            "type": "string",
            "description": "An active number of the workspace, bought, provisioned or fully ported into Sendly, in E.164 format."
          },
          "businessAccountId": {
            "type": "string",
            "description": "Adds the number to this connected WhatsApp Business account, by code, without the Facebook step. The account needs an active sender in this workspace."
          },
          "verificationMethod": {
            "type": "string",
            "enum": [
              "sms",
              "voice"
            ],
            "description": "With `businessAccountId`: how WhatsApp sends the code. Defaults to `sms`."
          },
          "displayName": {
            "type": "string",
            "maxLength": 512,
            "description": "With `businessAccountId`: the name WhatsApp shows for the number. Defaults to the account's sender display name, then its business name."
          }
        },
        "required": [
          "phoneNumber"
        ]
      },
      "StartWorkspaceUpgradeRequest": {
        "type": "object",
        "properties": {
          "businessName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500,
            "description": "The new entity's legal name."
          },
          "brn": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500,
            "description": "The new entity's business registration number."
          },
          "brnType": {
            "type": "string",
            "enum": [
              "EIN",
              "SSN",
              "DUNS",
              "CRA",
              "VAT",
              "LEI",
              "OTHER"
            ],
            "description": "What kind of number `brn` is, such as `EIN`."
          },
          "brnCountry": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "description": "The ISO 3166-1 alpha-2 country that issued `brn`, in capitals."
          },
          "entityType": {
            "type": "string",
            "enum": [
              "SOLE_PROPRIETOR",
              "PRIVATE_PROFIT",
              "PUBLIC_PROFIT",
              "NON_PROFIT",
              "GOVERNMENT"
            ],
            "description": "The new entity's legal form."
          },
          "doingBusinessAs": {
            "type": "string",
            "maxLength": 500,
            "description": "A trading name, if it differs from `businessName`."
          },
          "website": {
            "type": "string",
            "maxLength": 500,
            "description": "The business website, with its scheme (`https://`)."
          },
          "address1": {
            "type": "string",
            "maxLength": 500,
            "description": "The first line of the business address."
          },
          "address2": {
            "type": "string",
            "maxLength": 500,
            "description": "The second line of the business address."
          },
          "city": {
            "type": "string",
            "maxLength": 500,
            "description": "The business address's city."
          },
          "state": {
            "type": "string",
            "maxLength": 500,
            "description": "The state or province. A 2-letter US or Canadian code is changed to the full name."
          },
          "zip": {
            "type": "string",
            "maxLength": 500,
            "description": "The ZIP or postal code."
          },
          "addressCountry": {
            "type": "string",
            "description": "The address's ISO 3166-1 alpha-2 country code."
          },
          "contactFirstName": {
            "type": "string",
            "maxLength": 500,
            "description": "The contact's first name."
          },
          "contactLastName": {
            "type": "string",
            "maxLength": 500,
            "description": "The contact's last name."
          },
          "contactEmail": {
            "type": "string",
            "maxLength": 500,
            "description": "The contact's email address."
          },
          "contactPhone": {
            "type": "string",
            "maxLength": 500,
            "description": "The contact's phone number, in E.164 format."
          },
          "monthlyVolume": {
            "type": "string",
            "enum": [
              "10",
              "100",
              "1,000",
              "10,000",
              "100,000",
              "250,000",
              "500,000",
              "750,000",
              "1,000,000",
              "5,000,000",
              "10,000,000+"
            ],
            "description": "Expected messages a month."
          },
          "useCase": {
            "type": "string",
            "enum": [
              "2FA",
              "App Notifications",
              "Appointments",
              "Auctions",
              "Auto Repair Services",
              "Bank Transfers",
              "Billing",
              "Booking Confirmations",
              "Business Updates",
              "COVID-19 Alerts",
              "Career Training",
              "Chatbot",
              "Conversational / Alerts",
              "Courier Services & Deliveries",
              "Emergency Alerts",
              "Events & Planning",
              "Financial Services",
              "Fraud Alerts",
              "Fundraising",
              "General Marketing",
              "General School Updates",
              "HR / Staffing",
              "Healthcare Alerts",
              "Housing Community Updates",
              "Insurance Services",
              "Job Dispatch",
              "Legal Services",
              "Mixed",
              "Motivational Reminders",
              "Notary Notifications",
              "Order Notifications",
              "Political",
              "Public Works",
              "Real Estate Services",
              "Religious Services",
              "Repair and Diagnostics Alerts",
              "Rewards Program",
              "Surveys",
              "System Alerts",
              "Voting Reminders",
              "Waitlist Alerts",
              "Webinar Reminders",
              "Workshop Alerts"
            ],
            "description": "The messaging use case."
          },
          "useCaseSummary": {
            "type": "string",
            "maxLength": 500,
            "description": "What the messages are for, in a sentence or two."
          },
          "sampleMessages": {
            "type": "string",
            "maxLength": 1000,
            "description": "Example messages the workspace will send, with STOP opt-out language."
          },
          "optInWorkflow": {
            "type": "string",
            "maxLength": 500,
            "description": "How recipients agree to receive messages."
          },
          "privacyUrl": {
            "type": "string",
            "maxLength": 500,
            "description": "The privacy policy's URL."
          },
          "termsUrl": {
            "type": "string",
            "maxLength": 500,
            "description": "The terms and conditions' URL."
          },
          "additionalInformation": {
            "type": "string",
            "maxLength": 500,
            "description": "Anything else the reviewer should know."
          },
          "ageGatedContent": {
            "type": "string",
            "enum": [
              "true",
              "false"
            ],
            "description": "`true` when the messages are for adults only. Read as the string `true` or `false`: a JSON boolean is ignored on a start, and counts as `false` on a resubmit."
          }
        },
        "required": [
          "businessName",
          "brn",
          "brnType",
          "brnCountry",
          "entityType"
        ],
        "description": "The new business entity. Fields left out are copied from the workspace's current verification. The same fields can be sent as `multipart/form-data`, with the registration document as the file field `einDoc` (a PDF or image, up to 10 MB)."
      },
      "SubmitShortCodeApplicationRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ShortCodeApplicationInput"
          },
          {
            "type": "object",
            "properties": {
              "acceptTerms": {
                "type": "boolean",
                "enum": [
                  true
                ],
                "description": "Accepts the setup fee, the monthly lease and the minimum term."
              }
            },
            "required": [
              "acceptTerms"
            ]
          }
        ],
        "description": "Answers to save on the application. Every field is optional: a field left out keeps its saved value, and `null` or a blank string clears it. Strings are trimmed. Fields Sendly or the carriers own are not saved and are named back in `ignoredFields`."
      },
      "SubmittedPort": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The port request's id."
          },
          "status": {
            "type": "string",
            "description": "The carrier order's status after the submit, `in-process` when the carrier gave none. Known values are those of `PortRequest.status`.",
            "x-sendly-extensible-enum": [
              "draft",
              "pending",
              "submitted",
              "in-process",
              "exception",
              "foc-date-confirmed",
              "ownership_successful",
              "loa_file_successful",
              "in_review",
              "internal_transfer_pending",
              "rejected",
              "successful",
              "ported",
              "failed",
              "carrier_rejected",
              "ineligible_carrier",
              "cancelled",
              "deleted"
            ]
          },
          "submitted": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "id",
          "status",
          "submitted"
        ]
      },
      "SuggestRepliesDisabled": {
        "type": "object",
        "properties": {
          "suggestions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "text": {
                  "type": "string",
                  "description": "The suggested reply, up to 160 characters."
                },
                "tone": {
                  "type": "string",
                  "description": "The reply's tone. Known values: `professional`, `friendly`, `concise`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "professional",
                    "friendly",
                    "concise"
                  ]
                }
              },
              "required": [
                "text",
                "tone"
              ]
            },
            "maxItems": 0
          },
          "disabled": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "enterprise_policy"
            ]
          }
        },
        "required": [
          "suggestions",
          "disabled",
          "reason"
        ],
        "description": "The workspace's enterprise account has AI suggestions turned off.",
        "title": "Turned off by the enterprise"
      },
      "SuggestRepliesNone": {
        "type": "object",
        "properties": {
          "suggestions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "text": {
                  "type": "string",
                  "description": "The suggested reply, up to 160 characters."
                },
                "tone": {
                  "type": "string",
                  "description": "The reply's tone. Known values: `professional`, `friendly`, `concise`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "professional",
                    "friendly",
                    "concise"
                  ]
                }
              },
              "required": [
                "text",
                "tone"
              ]
            },
            "maxItems": 0
          }
        },
        "required": [
          "suggestions"
        ],
        "description": "No reply could be suggested: the conversation's first 10 messages have no inbound message, or the model failed, timed out or is not set up.",
        "title": "No suggestions"
      },
      "SuggestRepliesResult": {
        "type": "object",
        "properties": {
          "suggestions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "text": {
                  "type": "string",
                  "description": "The suggested reply, up to 160 characters."
                },
                "tone": {
                  "type": "string",
                  "description": "The reply's tone. Known values: `professional`, `friendly`, `concise`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "professional",
                    "friendly",
                    "concise"
                  ]
                }
              },
              "required": [
                "text",
                "tone"
              ]
            },
            "description": "The replies the model wrote. It is asked for two or three; the count is not checked."
          },
          "basedOnMessageId": {
            "type": "string",
            "description": "The inbound message the replies answer."
          },
          "model": {
            "type": "string",
            "description": "The model that wrote them."
          }
        },
        "required": [
          "suggestions",
          "basedOnMessageId",
          "model"
        ],
        "title": "Suggestions"
      },
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The template's id, such as `tpl_...`."
          },
          "name": {
            "type": "string",
            "description": "The template's name."
          },
          "text": {
            "type": "string",
            "description": "The message text, with `{{key}}` placeholders for its variables."
          },
          "variables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateVariable"
            },
            "description": "The `{{key}}` variables in the text, in order of first use. An empty array when there are none. An update that sets `variables` without `text` stores that array as sent instead."
          },
          "is_preset": {
            "type": "boolean",
            "description": "Whether this is one of Sendly's presets, shared by every account."
          },
          "preset_slug": {
            "type": [
              "string",
              "null"
            ],
            "description": "The preset's slug, such as `otp`. `null` for your own template."
          },
          "status": {
            "type": "string",
            "description": "`draft` can still be edited; `published` is locked. Known values: `draft`, `published`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "published"
            ]
          },
          "version": {
            "type": "integer",
            "description": "The template's version. Always 1 today."
          },
          "published_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the template was published. `null` for a draft."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the template was created. ISO 8601, in UTC."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the template was last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "text",
          "variables",
          "is_preset",
          "preset_slug",
          "status",
          "version",
          "published_at",
          "created_at",
          "updated_at"
        ],
        "description": "A template, as `GET /api/v1/templates` and `GET /api/v1/templates/{id}` return it."
      },
      "TemplateList": {
        "type": "object",
        "properties": {
          "templates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Template"
            }
          }
        },
        "required": [
          "templates"
        ]
      },
      "TemplatePreview": {
        "type": "object",
        "properties": {
          "template_id": {
            "type": "string",
            "description": "The template's id, such as `tpl_...`."
          },
          "original_text": {
            "type": "string",
            "description": "The template's text, unrendered."
          },
          "rendered_text": {
            "type": "string",
            "description": "The text with each `{{key}}` replaced by the value you sent, else the variable's fallback. A variable with neither stays as `{{key}}`."
          },
          "character_count": {
            "type": "integer",
            "description": "The rendered text's length, in UTF-16 code units."
          },
          "segment_count": {
            "type": "integer",
            "description": "How many SMS segments the rendered text needs."
          }
        },
        "required": [
          "template_id",
          "original_text",
          "rendered_text",
          "character_count",
          "segment_count"
        ]
      },
      "TemplateVariable": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "The variable's name, as it appears in `{{key}}` in the text."
          },
          "type": {
            "type": "string",
            "description": "The variable's type. Taken as sent from `variables` on create or update, `string` otherwise. Absent when an update set `variables` without `text` and the entry had none. Known values: `string`, `number`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "string",
              "number"
            ]
          },
          "fallback": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "description": "The value used when a send or preview gives none."
          }
        },
        "required": [
          "key"
        ]
      },
      "TemplateWithoutPresetSlug": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The template's id, such as `tpl_...`."
          },
          "name": {
            "type": "string",
            "description": "The template's name."
          },
          "text": {
            "type": "string",
            "description": "The message text, with `{{key}}` placeholders for its variables."
          },
          "variables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateVariable"
            },
            "description": "The `{{key}}` variables in the text, in order of first use. An empty array when there are none. An update that sets `variables` without `text` stores that array as sent instead."
          },
          "is_preset": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "status": {
            "type": "string",
            "description": "`draft` can still be edited; `published` is locked. Known values: `draft`, `published`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "draft",
              "published"
            ]
          },
          "version": {
            "type": "integer",
            "description": "The template's version. Always 1 today."
          },
          "published_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the template was published. `null` for a draft."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the template was created. ISO 8601, in UTC."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the template was last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "text",
          "variables",
          "is_preset",
          "status",
          "version",
          "published_at",
          "created_at",
          "updated_at"
        ],
        "description": "One of your templates, as publishing or cloning returns it: a `Template` without `preset_slug`."
      },
      "TenDlcAssignment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The assignment's id."
          },
          "campaignId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The campaign the number is assigned to."
          },
          "phoneNumber": {
            "type": "string",
            "description": "The number, in E.164 format."
          },
          "status": {
            "type": "string",
            "enum": [
              "Active",
              "Under review",
              "Action needed"
            ],
            "description": "`Active` once the carriers accept the number, `Action needed` when they refused it or it was removed, `Under review` otherwise."
          },
          "assignedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the assignment was made. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "campaignId",
          "phoneNumber",
          "status",
          "assignedAt"
        ],
        "description": "A phone number assigned to a campaign."
      },
      "TenDlcAssignmentList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenDlcAssignment"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "TenDlcAssignmentResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TenDlcAssignment"
          }
        },
        "required": [
          "data"
        ]
      },
      "TenDlcBrand": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The brand's id."
          },
          "legalName": {
            "type": "string",
            "description": "The legal business name."
          },
          "dba": {
            "type": [
              "string",
              "null"
            ],
            "description": "The \"doing business as\" name."
          },
          "entityType": {
            "type": "string",
            "description": "The business entity type, as sent, such as `PRIVATE_PROFIT` or `SOLE_PROPRIETOR`. `PRIVATE_PROFIT` when none was sent."
          },
          "ein": {
            "type": [
              "string",
              "null"
            ],
            "description": "The business registration number. `null` for a sole proprietor."
          },
          "vertical": {
            "type": [
              "string",
              "null"
            ],
            "description": "The industry vertical."
          },
          "website": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "description": "Where the brand is in review. `awaiting_review` and `changes_requested` are Sendly's own review before the carriers see it; `provisioning` is approved and being registered. Known values: `pending`, `verified`, `failed`, `awaiting_review`, `changes_requested`, `provisioning`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "pending",
              "verified",
              "failed",
              "awaiting_review",
              "changes_requested",
              "provisioning"
            ]
          },
          "identityStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "The identity check's own result, from the carrier review. `null` until the carrier network reports one. Known values: `PENDING`, `VERIFIED`, `VETTED_VERIFIED`, `SELF_DECLARED`, `UNVERIFIED`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "PENDING",
              "VERIFIED",
              "VETTED_VERIFIED",
              "SELF_DECLARED",
              "UNVERIFIED"
            ]
          },
          "smsOtpStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "The one-time code a sole proprietor's mobile number receives. `null` for any other entity type. Known values: `not_started`, `pending`, `verified`, `expired`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "not_started",
              "pending",
              "verified",
              "expired"
            ]
          },
          "mobileLast4": {
            "type": [
              "string",
              "null"
            ],
            "description": "The last four digits of the brand's mobile number, when it has one."
          },
          "failureReasons": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Why the review failed, in plain English. `null` when there is no reason on file."
          },
          "vetting": {
            "type": "null",
            "description": "Always `null` over the API."
          },
          "einDocument": {
            "type": "null",
            "description": "Always `null` over the API."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the brand was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the brand last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "legalName",
          "dba",
          "entityType",
          "ein",
          "vertical",
          "website",
          "status",
          "identityStatus",
          "smsOtpStatus",
          "mobileLast4",
          "failureReasons",
          "vetting",
          "einDocument",
          "createdAt",
          "updatedAt"
        ],
        "description": "A business identity registered for carrier review."
      },
      "TenDlcBrandList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenDlcBrand"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "TenDlcBrandResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TenDlcBrand"
          }
        },
        "required": [
          "data"
        ]
      },
      "TenDlcCampaign": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The campaign's id."
          },
          "brandId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The brand the campaign belongs to."
          },
          "useCase": {
            "type": "string",
            "description": "The use case, such as `MIXED` or `MARKETING`. Always `SOLE_PROPRIETOR` under a sole-proprietor brand."
          },
          "subUseCases": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The sub use cases, as sent. Empty when none were."
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "description": "Where the campaign is in review. `awaiting_review` and `changes_requested` are Sendly's own review before the carriers see it. Numbers can be assigned once it is `active`. Known values: `pending`, `active`, `failed`, `suspended`, `expired`, `awaiting_review`, `changes_requested`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "pending",
              "active",
              "failed",
              "suspended",
              "expired",
              "awaiting_review",
              "changes_requested"
            ]
          },
          "sampleMessages": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The first five sample messages sent."
          },
          "throughput": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TenDlcThroughput"
              },
              {
                "type": "null"
              },
              {
                "type": "null"
              }
            ],
            "description": "`null` until the carrier network reports throughput."
          },
          "failureReasons": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Why the review failed, in plain English. `null` when there is no reason on file."
          },
          "reviewNote": {
            "type": [
              "string",
              "null"
            ],
            "description": "What Sendly's review asked to change, when it did."
          },
          "resubmissionCount": {
            "type": "integer",
            "description": "Paid resubmissions made after a carrier rejection."
          },
          "resubmissionLimitReached": {
            "type": "boolean",
            "description": "`true` when a failed campaign has used both of its paid resubmissions."
          },
          "deletable": {
            "type": "boolean",
            "description": "Whether the campaign is a draft that never reached the carriers, and so can be discarded."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the campaign was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the campaign last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "brandId",
          "useCase",
          "subUseCases",
          "description",
          "status",
          "sampleMessages",
          "throughput",
          "failureReasons",
          "reviewNote",
          "resubmissionCount",
          "resubmissionLimitReached",
          "deletable",
          "createdAt",
          "updatedAt"
        ],
        "description": "A messaging campaign registered for carrier review."
      },
      "TenDlcCampaignList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenDlcCampaign"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "TenDlcCampaignResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TenDlcCampaign"
          }
        },
        "required": [
          "data"
        ]
      },
      "TenDlcQualifyResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TenDlcQualifyResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "TenDlcQualifyResult": {
        "type": "object",
        "properties": {
          "useCase": {
            "type": "string",
            "description": "The use case checked, as it was in the path."
          },
          "qualified": {
            "type": "boolean"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the use case does not qualify, when the carrier network gave a reason."
          },
          "throughput": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TenDlcThroughput"
              },
              {
                "type": "null"
              },
              {
                "type": "null"
              }
            ],
            "description": "The throughput to expect, when the carrier network reports it."
          }
        },
        "required": [
          "useCase",
          "qualified",
          "reason",
          "throughput"
        ],
        "description": "Whether a use case qualifies for a brand on the carrier network."
      },
      "TenDlcThroughput": {
        "type": "object",
        "properties": {
          "tier": {
            "type": "string",
            "enum": [
              "High volume",
              "Standard",
              "Low volume"
            ],
            "description": "The throughput the carrier network grants, as a label."
          },
          "carriersReady": {
            "type": "integer",
            "description": "How many carriers have accepted the campaign or use case so far."
          }
        },
        "required": [
          "tier",
          "carriersReady"
        ],
        "description": "Throughput granted by the carrier network, without carrier names or ids."
      },
      "TotalPagination": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "How many items match, across every page."
          }
        },
        "required": [
          "total"
        ],
        "description": "Only the total, with no page position."
      },
      "TransferCreditsRequest": {
        "type": "object",
        "properties": {
          "targetOrganizationId": {
            "type": "string",
            "minLength": 1,
            "description": "The workspace to move the credits to. You must own it."
          },
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "How many credits to move: a positive whole number."
          }
        },
        "required": [
          "targetOrganizationId",
          "amount"
        ]
      },
      "UnhandledServerError": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "enum": [
              "Internal Server Error"
            ]
          },
          "sendlyCode": {
            "type": "string",
            "enum": [
              "internal_error"
            ],
            "description": "The registered code for this error, added beside the body's existing fields, which keep their names and values. A server from before the error envelope does not send it."
          }
        },
        "required": [
          "message"
        ],
        "description": "Sent by the server's last error handler, with status 500 and no `error` code, when a route handler or middleware fails without answering itself: it threw, or its promise rejected. The error's own message is only logged.",
        "title": "Unhandled server error",
        "x-sendly-error-shape": "codeless",
        "x-sendly-error-codes": [],
        "x-sendly-proposed-codes": [
          "internal_error"
        ]
      },
      "UnsupportedMediaTypeError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "unsupported_media_type"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "description": "Sent by the server's last error handler when the upload middleware refuses a file for its declared type, before the handler runs. `message` names the types the endpoint takes.",
        "title": "Unsupported file type",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "unsupported_media_type"
        ]
      },
      "UpdateAutoLabelRuleRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "conditions": {
            "type": "object",
            "properties": {
              "intent": {
                "anyOf": [
                  {
                    "type": "string",
                    "description": "An intent the message classifier gives an inbound message. Known values: `question`, `appointment`, `complaint`, `order_status`, `feedback`, `opt_out`, `greeting`, `confirmation`, `other`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "question",
                      "appointment",
                      "complaint",
                      "order_status",
                      "feedback",
                      "opt_out",
                      "greeting",
                      "confirmation",
                      "other"
                    ]
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "An intent the message classifier gives an inbound message. Known values: `question`, `appointment`, `complaint`, `order_status`, `feedback`, `opt_out`, `greeting`, `confirmation`, `other`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "question",
                        "appointment",
                        "complaint",
                        "order_status",
                        "feedback",
                        "opt_out",
                        "greeting",
                        "confirmation",
                        "other"
                      ]
                    },
                    "minItems": 1
                  }
                ],
                "description": "Match this intent, or any intent in the list. Absent matches every intent."
              },
              "sentiment": {
                "anyOf": [
                  {
                    "type": "string",
                    "description": "A sentiment the message classifier gives an inbound message. Known values: `positive`, `neutral`, `negative`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "positive",
                      "neutral",
                      "negative"
                    ]
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "A sentiment the message classifier gives an inbound message. Known values: `positive`, `neutral`, `negative`. More can be added at any time, so treat an unknown value as valid.",
                      "x-sendly-extensible-enum": [
                        "positive",
                        "neutral",
                        "negative"
                      ]
                    },
                    "minItems": 1
                  }
                ],
                "description": "Match this sentiment, or any sentiment in the list. Absent matches every sentiment."
              },
              "intentConfidenceMin": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Match only when the classifier is at least this sure of the intent, 0 to 1."
              },
              "sentimentConfidenceMin": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "Match only when the classifier is at least this sure of the sentiment, 0 to 1."
              }
            },
            "additionalProperties": false,
            "description": "Replaces the conditions as a whole."
          },
          "actions": {
            "type": "object",
            "properties": {
              "addLabels": {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "description": "A label's id."
                },
                "description": "Labels to add to the conversation. An id that is not one of the workspace's labels is skipped when the rule runs. Stored as `[]` when absent."
              },
              "closeConversation": {
                "type": "boolean",
                "description": "`true` closes the conversation."
              }
            },
            "additionalProperties": false,
            "description": "Replaces the actions as a whole."
          },
          "enabled": {
            "type": "boolean",
            "description": "`false` stops the rule running."
          },
          "priority": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": -2147483648,
            "maximum": 2147483647,
            "description": "Rules run lowest first. `null` leaves it as it is."
          }
        },
        "description": "Only the fields sent change, each checked against its type as on create. An empty body only moves `updatedAt`. Any other field is ignored."
      },
      "UpdateAutoTopUpRequest": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Left out means `false`."
          },
          "threshold": {
            "type": "number",
            "description": "Left out means 0."
          },
          "amount": {
            "type": "number",
            "description": "Required above 0 when `enabled` is `true`. Left out means 0."
          },
          "sourceWorkspaceId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace credits are moved from, which the key's owner must own when `enabled` is `true`."
          }
        }
      },
      "UpdateCampaignRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255,
            "description": "The campaign's name."
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "The message. `{{name}}` and `{{brand_name}}` are filled in per recipient. An empty or blank text counts as none."
          },
          "messageText": {
            "type": [
              "string",
              "null"
            ],
            "description": "The same as `text`, and preferred over it when both are sent."
          },
          "templateId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Fill the message from a template of this workspace or a preset, when no text is sent. The template may use only `{{name}}` and `{{brand_name}}`."
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The same as `templateId`."
          },
          "contactListIds": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "maxItems": 1,
            "description": "The contact list to target, as a one-element array. More than one id answers 400; an empty array clears the list."
          },
          "contact_list_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "maxItems": 1,
            "description": "The same as `contactListIds`."
          },
          "contactListId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact list to target, as a single id."
          },
          "targetListId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact list to target. Takes precedence over the other list fields; `null` clears it."
          },
          "targetType": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "contact_list",
              "all_contacts",
              "manual",
              null
            ],
            "description": "Who to send to. Defaults to `contact_list`, which is also what any list field implies."
          },
          "manualRecipients": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "phone": {
                  "type": "string",
                  "description": "A phone number in E.164 format."
                },
                "name": {
                  "type": "string"
                }
              },
              "required": [
                "phone"
              ]
            },
            "description": "The recipients of a `manual` campaign."
          },
          "excludeOptedOut": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Stored only: opted-out contacts are always left out."
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Defaults to `America/New_York`."
          },
          "fromSender": {
            "type": [
              "string",
              "null"
            ],
            "description": "The number a scheduled send goes from. `POST /api/v1/campaigns/{id}/send` ignores it and uses its own `from`."
          }
        },
        "description": "The fields to change. A `null` for `name`, `text`, `messageText`, `templateId`, `targetType`, `excludeOptedOut`, `timezone` or a contact list field other than `targetListId` leaves it as it is. A `null` for `targetListId`, `fromSender` or `manualRecipients` clears it. A `status` is never written: schedule and cancel change it."
      },
      "UpdateContactListRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "\\S",
            "description": "A new name. Trimmed, and it must not be blank. `null` or absent leaves the name as it is."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "A new description. `null` or an empty string clears it; absent leaves it as it is."
          }
        },
        "description": "Every field is optional. An empty body changes nothing but `updated_at`."
      },
      "UpdateConversationRequest": {
        "type": "object",
        "properties": {
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "Replaces the conversation's metadata as a whole, with no merge and no size limit. On a group conversation this also drops `isGroup`, `groupKey` and `participants`."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Replaces the conversation's tags as a whole."
          }
        }
      },
      "UpdateDraftRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The new reply text."
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The new media URLs, replacing the old ones."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The new metadata, replacing the old object."
          }
        },
        "description": "Only the fields you send change. Any other field is ignored."
      },
      "UpdateNumberRequest": {
        "type": "object",
        "properties": {
          "isDefault": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "`true` makes the number the workspace's default sender and clears the previous default. The number must be `active`. Any other value is ignored."
          },
          "pendingCancellation": {
            "type": "boolean",
            "enum": [
              false
            ],
            "description": "`false` cancels a scheduled release and keeps the number. On a number with no scheduled release it changes nothing. Any other value is ignored."
          }
        },
        "description": "At least one of the two fields. With both, the scheduled release is cancelled first, so it stays cancelled even when the number cannot become the default."
      },
      "UpdateRcsAgentRequest": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The agent's name. Takes precedence over `basics.displayName`."
          },
          "useCase": {
            "type": [
              "string",
              "null"
            ],
            "description": "Takes precedence over `basics.useCase`."
          },
          "basics": {
            "type": "object",
            "properties": {
              "displayName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "useCase": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "One of `MULTI_USE`, `PROMOTIONAL`, `TRANSACTIONAL`, `OTP`."
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "logoUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A public `https://` URL. Uploading is not available over the API."
              },
              "heroUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A public `https://` URL. Uploading is not available over the API."
              },
              "brandColor": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A hex color, such as `#2563EB`."
              },
              "privacyPolicyUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "termsAndConditionsUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "phoneNumber": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "number": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "website": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "email": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "address": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "label": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              }
            }
          },
          "campaign": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "companyOverview": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "agentOverview": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "additionalInformation": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "interactions": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "object",
                  "properties": {
                    "interactionType": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "messageExamples": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "consentSettings": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "callToAction": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "callToActionUrl": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "callToActionMediaUrl": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "A public `https://` URL. Uploading is not available over the API."
                  },
                  "doubleOptIn": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "doubleOptInMessage": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "optInMessage": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "helpResponse": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "optOutResponse": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "optInMethods": {
                    "type": [
                      "array",
                      "null"
                    ],
                    "items": {
                      "type": "object",
                      "properties": {
                        "methodType": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            },
            "description": "Merged into the stored campaign, one top-level field at a time. `null` clears it."
          },
          "testing": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "testUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "messageId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "additionalInformation": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "description": "Merged into the stored testing details. `null` clears them."
          }
        },
        "description": "The fields to change. A field left out keeps its value."
      },
      "UpdateRcsBrandRequest": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": [
              "string",
              "null"
            ]
          },
          "legalName": {
            "type": [
              "string",
              "null"
            ]
          },
          "legalEntityType": {
            "type": [
              "string",
              "null"
            ],
            "description": "One of `LIMITED_LIABILITY_COMPANY`, `SOLE_PROPRIETORSHIP`, `PARTNERSHIP`, `CORPORATION`, `S_CORPORATION`."
          },
          "organizationType": {
            "type": [
              "string",
              "null"
            ],
            "description": "One of `PRIVATE_PROFIT`, `PUBLIC_PROFIT`, `NON_PROFIT`, `GOVERNMENT`, `UNKNOWN`."
          },
          "websiteUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "ein": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nine digits, as `123456789` or `12-3456789`."
          },
          "stockSymbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "`EXCHANGE:SYMBOL`, for a public company."
          },
          "contact": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "firstName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "lastName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "phoneNumber": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "In E.164 format."
              }
            }
          },
          "address": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "line1": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "line2": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "city": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "state": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "postalCode": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "countryCode": {
                "type": "string",
                "description": "`US`, in any case, when sent."
              }
            }
          }
        },
        "description": "The fields to change. A field left out keeps its value."
      },
      "UpdateTemplateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "\\S",
            "description": "A new name. Trimmed."
          },
          "text": {
            "type": "string",
            "maxLength": 1600,
            "pattern": "\\S",
            "description": "New text, up to 1,600 characters before trimming. The variables are read from it again."
          },
          "variables": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "description": "The variable's name in the text."
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "string",
                    "number"
                  ],
                  "description": "Defaults to `string`."
                },
                "fallback": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "number"
                    }
                  ],
                  "description": "The value to use when a send gives none."
                }
              },
              "required": [
                "key"
              ]
            },
            "description": "With `text`, types and fallbacks for its variables, matched by `key`; without it, the stored variables keep theirs. Without `text`, this array replaces the stored variables as sent."
          }
        },
        "description": "At least one field."
      },
      "UpdateVerifyProfileRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "\\S",
            "description": "Not blank. Stored trimmed."
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "A template of this workspace, or a preset. `null` clears it."
          },
          "app_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "An empty value or `null` clears it."
          },
          "default_timeout_secs": {
            "type": "integer",
            "minimum": 60,
            "maximum": 3600
          },
          "code_length": {
            "type": "integer",
            "minimum": 4,
            "maximum": 10
          },
          "max_attempts": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10
          },
          "allowed_countries": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "An empty value or `null` allows every country."
          },
          "webhook_url": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(https:\\/\\/.*)?$",
            "description": "An `https://` URL. An empty value or `null` clears it."
          }
        },
        "description": "At least one field."
      },
      "UpdateVoiceAgentRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "description": "The agent's name, 1 to 80 characters after trimming."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the agent answers calls. `false` is refused with 409 while numbers still send their calls to the agent."
          },
          "voice": {
            "type": "string",
            "maxLength": 120,
            "description": "A voice id from `GET /api/v1/voice/voices`. Empty or unknown, the agent gets `ashley`, the default."
          },
          "language": {
            "type": "string",
            "maxLength": 16,
            "description": "A language tag such as `en-US`, up to 16 characters. Empty, the voice's own language is used."
          },
          "greeting": {
            "type": "string",
            "maxLength": 500,
            "description": "What the agent says when it answers, up to 500 characters. Empty removes it."
          },
          "instructions": {
            "type": "string",
            "maxLength": 4000,
            "description": "How the agent should handle a call, up to 4,000 characters. Empty removes them."
          },
          "tools": {
            "type": "object",
            "properties": {
              "sendSms": {
                "type": "boolean",
                "description": "Whether the agent may text the caller."
              },
              "transferTo": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 20,
                "pattern": "^$|^\\+[1-9]\\d{6,14}$",
                "description": "A number in E.164 format to transfer callers to when they ask for a person. An empty string or `null` removes it."
              },
              "backgroundAudio": {
                "type": "boolean",
                "description": "Whether the agent plays quiet background sound during a call."
              }
            },
            "description": "What the agent can do during a call. Only the fields sent change."
          }
        }
      },
      "UpdateVoiceNumberRequest": {
        "type": "object",
        "properties": {
          "voiceEnabled": {
            "type": "boolean",
            "description": "Switch calls on or off for the number. Switching on is a change on the carrier network and can fail with 503."
          },
          "voiceMode": {
            "type": "string",
            "enum": [
              "none",
              "ring_dashboard",
              "agent"
            ],
            "description": "How the number answers. `ring_dashboard` or `agent` without `voiceEnabled` switches voice on, and `none` without it switches voice off."
          },
          "agentId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The agent to answer the number. Needed for `voiceMode` `agent`. `null` or an empty string clears it."
          }
        }
      },
      "UpdateWebhookRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "A new URL. `https://` is added when there is no protocol, and any other URL that does not start with `https://` is refused with 400 `invalid_url`, unless it is the webhook's current URL sent back unchanged. Unlike on create, a test key is not limited to test URLs and the URL is not checked for private networks here. A new URL also resets the circuit breaker."
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.sent",
                "message.delivered",
                "message.read",
                "message.failed",
                "message.bounced",
                "message.retrying",
                "message.received",
                "message.opt_out",
                "message.opt_in",
                "verification.created",
                "verification.delivered",
                "verification.verified",
                "verification.expired",
                "verification.failed",
                "verification.resent",
                "verification.delivery_failed",
                "conversation.created",
                "conversation.updated",
                "draft.created",
                "draft.approved",
                "draft.rejected",
                "contact.auto_flagged",
                "contact.marked_valid",
                "contacts.lookup_completed",
                "contacts.bulk_marked_valid",
                "brand.verified",
                "brand.failed",
                "campaign.approved",
                "campaign.rejected",
                "campaign.suspended",
                "assignment.confirmed",
                "assignment.failed",
                "rcs_brand.verified",
                "rcs_brand.failed",
                "rcs_agent.testing",
                "rcs_agent.live",
                "rcs_agent.rejected",
                "rcs_agent.action_required",
                "port.completed",
                "port_out.requested",
                "port_out.completed",
                "port_out.rejected",
                "port_out.cancelled",
                "number.activated",
                "number.failed",
                "number.requirements_required",
                "number.released",
                "whatsapp_account.connected",
                "whatsapp_account.failed",
                "whatsapp_template.approved",
                "whatsapp_template.rejected",
                "whatsapp_template.paused",
                "call.started",
                "call.completed",
                "call.recording.ready",
                "short_code.action_required",
                "short_code.rejected",
                "short_code.filed",
                "short_code.live",
                "short_code.suspended",
                "short_code.reactivated",
                "short_code.cancelled",
                "short_code.payment_succeeded",
                "short_code.payment_failed"
              ]
            },
            "description": "Replaces the subscribed events. An empty array is accepted and subscribes to none."
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "all",
              "test",
              "live"
            ],
            "description": "`live` needs a verified business."
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "is_active": {
            "type": "boolean",
            "description": "`false` stops deliveries: new events are neither sent nor recorded, and queued retries end as failed or cancelled."
          },
          "isActive": {
            "type": "boolean",
            "description": "Read when `is_active` is absent or `null`."
          }
        },
        "description": "At least one field. A `null` `url`, `events` or `mode` is ignored."
      },
      "UpdateWhatsAppCallingRequest": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "`true` turns calling on."
          }
        },
        "required": [
          "enabled"
        ]
      },
      "UpdateWhatsAppConversationalComponentsRequest": {
        "type": "object",
        "properties": {
          "iceBreakers": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 80,
              "pattern": "\\S"
            },
            "maxItems": 4,
            "description": "Replaces the ice breakers: at most 4, each 1 to 80 characters after trimming, no two the same ignoring case. `[]` clears them."
          },
          "commands": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "pattern": "^\\/?[A-Za-z0-9_]{1,32}$",
                  "description": "Letters, digits or underscores, 1 to 32 of them. A leading `/` is dropped."
                },
                "description": {
                  "type": "string",
                  "maxLength": 256,
                  "pattern": "\\S",
                  "description": "What the command does: 1 to 256 characters after trimming."
                }
              },
              "required": [
                "command",
                "description"
              ]
            },
            "maxItems": 30,
            "description": "Replaces the commands: at most 30, no command twice ignoring case. `[]` clears them."
          }
        },
        "additionalProperties": false,
        "description": "At least one of the two lists. Any other field is refused with 400.",
        "minProperties": 1
      },
      "UpdateWhatsAppSenderProfileRequest": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": "string",
            "description": "The business name recipients see."
          },
          "about": {
            "type": "string",
            "maxLength": 139,
            "description": "Up to 139 characters."
          },
          "description": {
            "type": "string",
            "maxLength": 512,
            "description": "Up to 512 characters."
          },
          "category": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "address": {
            "type": "string"
          }
        },
        "additionalProperties": false,
        "description": "At least one field. Fields left out keep their value. Any other field is refused with 400.",
        "minProperties": 1
      },
      "UpdateWhatsAppTemplateRequest": {
        "type": "object",
        "properties": {
          "body": {
            "type": "string",
            "maxLength": 1024,
            "pattern": "\\S",
            "description": "The new body text, up to 1,024 characters. Except in an `AUTHENTICATION` template, it cannot start or end with a variable."
          },
          "footer": {
            "type": "string",
            "maxLength": 60,
            "description": "A footer line, up to 60 characters."
          },
          "header": {
            "type": "string",
            "pattern": "^(?![\\s\\S]*\\{\\{\\s*\\d+\\s*\\}\\})",
            "description": "A fixed text header. A `{{n}}` variable in it is refused."
          },
          "buttons": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "url"
                      ],
                      "description": "Opens a link. Matched ignoring case."
                    },
                    "text": {
                      "type": "string",
                      "maxLength": 25,
                      "description": "The button's label, up to 25 characters."
                    },
                    "url": {
                      "type": "string",
                      "minLength": 1,
                      "description": "The link, which may hold a `{{1}}` variable."
                    },
                    "example": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Example values for the link's variable."
                    }
                  },
                  "required": [
                    "type",
                    "text",
                    "url"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "quick_reply"
                      ],
                      "description": "Sends its label back. Matched ignoring case."
                    },
                    "text": {
                      "type": "string",
                      "maxLength": 25,
                      "description": "The button's label, up to 25 characters."
                    }
                  },
                  "required": [
                    "type",
                    "text"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "otp"
                      ],
                      "description": "Copies a code. Required on an `AUTHENTICATION` template, where it is the only kind allowed besides `quick_reply`. Matched ignoring case."
                    },
                    "text": {
                      "type": "string",
                      "maxLength": 25,
                      "description": "The button's label, up to 25 characters. Defaults to `Copy code`."
                    }
                  },
                  "required": [
                    "type"
                  ]
                }
              ],
              "description": "A button: `url`, `quick_reply` or `otp`."
            },
            "maxItems": 3,
            "description": "Up to 3 buttons."
          },
          "examples": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "An example value for every body variable, by number: `{\"1\": \"A1234\"}`. Required when the body has variables."
          }
        }
      },
      "UpdatedPhoneNumber": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The number's id."
          },
          "phoneNumber": {
            "type": "string",
            "description": "The number, in E.164 format."
          },
          "status": {
            "type": "string",
            "description": "Where the number is in its lifecycle. Only an `active` number can send. A `requirements_required` number with `requirementsSubmittedAt` set is under review; without it, it still needs documents. Released numbers are never listed. Known values: `active`, `provisioning`, `requirements_required`, `failed`, `suspended`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "active",
              "provisioning",
              "requirements_required",
              "failed",
              "suspended"
            ]
          },
          "source": {
            "type": "string",
            "description": "How the workspace got the number: bought here, set up through toll-free verification, hosted for SMS, or ported in. Known values: `purchased`, `provisioned`, `ported_hosted_sms`, `ported_full`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "purchased",
              "provisioned",
              "ported_hosted_sms",
              "ported_full"
            ]
          },
          "countryCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "The ISO 3166-1 alpha-2 country code. `null` on some older numbers that were never stamped with one."
          },
          "phoneNumberType": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` when the number's type was never recorded.",
            "x-sendly-extensible-enum": [
              "local",
              "toll_free",
              "mobile",
              "national"
            ]
          },
          "monthlyCostCents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The monthly price, in US cents. `null` for a number that is not billed monthly, such as a toll-free verified number."
          },
          "requirementsSubmittedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the number's registration details and documents were submitted for review. ISO 8601, in UTC."
          },
          "pendingCancellation": {
            "type": "boolean",
            "description": "`true` when the number is scheduled to be released at the end of the paid month."
          },
          "scheduledReleaseAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When a scheduled release takes effect. ISO 8601, in UTC."
          },
          "isDefault": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether this is the workspace's default sender. `null` on a number stored without the flag."
          }
        },
        "required": [
          "id",
          "phoneNumber",
          "status",
          "source",
          "countryCode",
          "phoneNumberType",
          "monthlyCostCents",
          "requirementsSubmittedAt",
          "pendingCancellation",
          "scheduledReleaseAt",
          "isDefault"
        ],
        "description": "The number after `PATCH /api/v1/numbers/{id}`: the fields of `PhoneNumber` without `voiceEnabled` and `voiceMode`."
      },
      "UploadMediaRequest": {
        "type": "object",
        "properties": {
          "file": {
            "type": "string",
            "description": "One JPEG, PNG or GIF image, up to 600 KB. The part's own `Content-Type` must be `image/jpeg`, `image/png` or `image/gif`, and the bytes must be an image of one of those types.",
            "format": "binary"
          }
        },
        "required": [
          "file"
        ]
      },
      "UploadedMedia": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The media file's id, starting with `upload_`."
          },
          "url": {
            "type": "string",
            "description": "The public URL of the stored image. Pass it in `mediaUrls` on `POST /api/v1/messages` to send it as an MMS."
          },
          "contentType": {
            "type": "string",
            "enum": [
              "image/jpeg",
              "image/png",
              "image/gif"
            ],
            "description": "The stored image's type, read from the file's bytes."
          },
          "sizeBytes": {
            "type": "integer",
            "description": "The stored size in bytes. A JPEG or PNG is re-encoded after it is turned upright, so this can differ from the size you uploaded."
          }
        },
        "required": [
          "id",
          "url",
          "contentType",
          "sizeBytes"
        ],
        "description": "A stored image, as `POST /api/v1/media` returns it. Its fields are camelCase, while `GET /api/v1/media` lists the same file in snake_case."
      },
      "ValidateSessionTokenRequest": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "minLength": 1,
            "description": "The token the hosted page added to `success_url`."
          }
        },
        "required": [
          "token"
        ]
      },
      "ValidateSessionTokenResult": {
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "phone": {
            "type": "string",
            "description": "The phone number the user verified."
          },
          "verified_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the user's code was checked. ISO 8601, in UTC."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The session's metadata, or `{}` when none was sent."
          }
        },
        "required": [
          "valid",
          "phone",
          "verified_at",
          "metadata"
        ]
      },
      "Verification": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The verification's id, such as `ver_...`."
          },
          "status": {
            "type": "string",
            "description": "Where the verification is. `pending` until the right code is checked, `verified` after it, `expired` once `expires_at` passes without a match, and `failed` when every attempt was used or the code could not be sent. Known values: `pending`, `verified`, `expired`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "pending",
              "verified",
              "expired",
              "failed"
            ]
          },
          "phone": {
            "type": "string",
            "description": "The phone number the code was sent to, as sent in `to`."
          },
          "delivery_status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where the code's SMS is. A sandbox verification is `delivered` at once. Known values: `queued`, `sent`, `delivered`, `failed`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "queued",
              "sent",
              "delivered",
              "failed"
            ]
          },
          "attempts": {
            "type": "integer",
            "description": "How many wrong codes were checked."
          },
          "max_attempts": {
            "type": "integer",
            "description": "How many codes may be checked in all."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the code expires. ISO 8601, in UTC."
          },
          "verified_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the right code was checked. ISO 8601, in UTC."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the verification was created. ISO 8601, in UTC."
          },
          "sandbox": {
            "type": "boolean",
            "description": "Whether a test key created it, so no SMS was sent."
          },
          "app_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The app name the message used."
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The template the message used. `tpl_preset_otp` by default."
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The verify profile it was sent with, if any."
          }
        },
        "required": [
          "id",
          "status",
          "phone",
          "delivery_status",
          "attempts",
          "max_attempts",
          "expires_at",
          "verified_at",
          "created_at",
          "sandbox",
          "app_name",
          "template_id",
          "profile_id"
        ],
        "description": "A verification, as `GET /api/v1/verify` and `GET /api/v1/verify/{id}` return it."
      },
      "VerificationDocumentUpload": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "The stored document's public URL."
          },
          "id": {
            "type": "string",
            "description": "The upload's id, `upload_` and 32 hex characters."
          }
        },
        "required": [
          "url",
          "id"
        ]
      },
      "VerificationList": {
        "type": "object",
        "properties": {
          "verifications": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Verification"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/LimitHasMorePagination"
          }
        },
        "required": [
          "verifications",
          "pagination"
        ]
      },
      "VerifyProfile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The profile's id, such as `vp_...`."
          },
          "name": {
            "type": "string"
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The template its codes use, or `null` for the default."
          },
          "app_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The app name its codes use, or `null` for the default."
          },
          "default_timeout_secs": {
            "type": "integer",
            "description": "Seconds until a code expires."
          },
          "code_length": {
            "type": "integer",
            "description": "Digits in a code."
          },
          "max_attempts": {
            "type": "integer",
            "description": "How many codes may be checked in all."
          },
          "allowed_countries": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "The country codes, as stored, that codes may be sent to. `null` or an empty list allows every country."
          },
          "webhook_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The URL as stored. Nothing is sent to it: verification events go to the workspace's webhooks."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the profile was created. ISO 8601, in UTC."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the profile was last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "template_id",
          "app_name",
          "default_timeout_secs",
          "code_length",
          "max_attempts",
          "allowed_countries",
          "webhook_url",
          "created_at",
          "updated_at"
        ],
        "description": "A verify profile: defaults for sending codes."
      },
      "VerifyProfileList": {
        "type": "object",
        "properties": {
          "profiles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VerifyProfile"
            }
          }
        },
        "required": [
          "profiles"
        ]
      },
      "VerifySession": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The session's id, such as `ses_...`."
          },
          "url": {
            "type": "string",
            "description": "The hosted page to send the user to."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending"
            ]
          },
          "success_url": {
            "type": "string"
          },
          "cancel_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "brand_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "brand_color": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "The metadata, as sent, or `null` when none was sent."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the session expires, 30 minutes after it was created. ISO 8601, in UTC."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the session was created. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "url",
          "status",
          "success_url",
          "cancel_url",
          "brand_name",
          "brand_color",
          "metadata",
          "expires_at",
          "created_at"
        ]
      },
      "VerifyWhatsAppSignupRequest": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "pattern": "^[\\s-]*(?:\\d[\\s-]*){6}$",
            "description": "The 6-digit code. Spaces and dashes are ignored, so `123-456` works."
          }
        },
        "required": [
          "code"
        ]
      },
      "VoiceAgent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The agent's id."
          },
          "object": {
            "type": "string",
            "enum": [
              "voice_agent"
            ]
          },
          "name": {
            "type": "string",
            "description": "The agent's name, up to 80 characters."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the agent answers calls. A number can only be pointed at an enabled agent."
          },
          "voice": {
            "type": "string",
            "description": "A voice from `GET /api/v1/voice/voices`. An agent whose stored voice is no longer offered reports `ashley`, the default. Known values: `ashley`, `edward`, `olivia`, `jacqueline`, `diego`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "ashley",
              "edward",
              "olivia",
              "jacqueline",
              "diego"
            ]
          },
          "voiceLabel": {
            "type": "string",
            "description": "The voice's display name, such as `Ashley (US, warm)`."
          },
          "language": {
            "type": "string",
            "description": "The language tag the agent speaks, such as `en-US` or `es-MX`. Defaults to the voice's own language."
          },
          "greeting": {
            "type": "string",
            "description": "What the agent says when it answers. Empty when it has none."
          },
          "instructions": {
            "type": "string",
            "description": "How the agent should handle a call, in plain language. Empty when it has none."
          },
          "tools": {
            "$ref": "#/components/schemas/VoiceAgentTools"
          },
          "canSendSms": {
            "type": "boolean",
            "description": "Whether the agent holds its own sending key, so that it can text. Creating or updating an agent issues one; revoking that key from the API keys page clears it until the agent is saved again."
          },
          "callsHandled": {
            "type": "integer",
            "description": "How many calls the agent answered and finished. 0 when the counts could not be read, and always 0 on a newly created agent."
          },
          "avgDurationSecs": {
            "type": "integer",
            "description": "The average length of those calls in seconds, rounded to a whole second. 0 when there are none."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the agent was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the agent was last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "enabled",
          "voice",
          "voiceLabel",
          "language",
          "greeting",
          "instructions",
          "tools",
          "canSendSms",
          "callsHandled",
          "avgDurationSecs",
          "createdAt",
          "updatedAt"
        ],
        "description": "An AI agent that answers or places phone calls."
      },
      "VoiceAgentList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VoiceAgent"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "VoiceAgentTools": {
        "type": "object",
        "properties": {
          "sendSms": {
            "type": "boolean",
            "description": "Whether the agent may text the caller during a call. Defaults to `true`. It can only text when `canSendSms` is `true` as well."
          },
          "transferTo": {
            "type": [
              "string",
              "null"
            ],
            "description": "The number, in E.164 format, the agent transfers a caller to when asked for a person. `null` when the agent cannot transfer."
          },
          "backgroundAudio": {
            "type": "boolean",
            "description": "Whether the agent plays quiet background sound during a call. Defaults to `false`."
          }
        },
        "required": [
          "sendSms",
          "transferTo",
          "backgroundAudio"
        ],
        "description": "What the agent can do during a call."
      },
      "VoiceInternalError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "voice_internal_error"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "voice_internal_error",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "voice_internal_error"
        ]
      },
      "VoiceNotEnabledError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "voice_not_enabled"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "voice_not_enabled",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "voice_not_enabled"
        ]
      },
      "VoiceNumber": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The number's id."
          },
          "object": {
            "type": "string",
            "enum": [
              "voice_number"
            ]
          },
          "phoneNumber": {
            "type": "string",
            "description": "The phone number, in E.164 format."
          },
          "phoneNumberType": {
            "type": [
              "string",
              "null"
            ],
            "description": "The kind of number, as it was bought or ported: `local`, `toll_free` or `mobile`, among others."
          },
          "countryCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "The number's two-letter country code, such as `US`."
          },
          "isDefault": {
            "type": "boolean",
            "description": "Whether this is the workspace's default number."
          },
          "voiceEnabled": {
            "type": "boolean",
            "description": "Whether calls to and from this number are switched on."
          },
          "voiceMode": {
            "type": "string",
            "enum": [
              "none",
              "ring_dashboard",
              "agent"
            ],
            "description": "How the number answers: `ring_dashboard` rings the team in the dashboard, `agent` hands the call to `agentId`, and `none` means voice is off."
          },
          "agentId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The agent set to answer the number, kept even while `voiceMode` is not `agent`."
          },
          "emergencyAddress": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "status": {
                "type": "string",
                "description": "Where the emergency registration is. `provisioning` until the carrier network confirms it. Known values: `provisioning`, `active`, `deprovisioning`, `disabled`, `provisioning-failed`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "provisioning",
                  "active",
                  "deprovisioning",
                  "disabled",
                  "provisioning-failed"
                ]
              },
              "address": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "street": {
                    "type": "string"
                  },
                  "unit": {
                    "type": "string",
                    "description": "Present only when the address has one."
                  },
                  "city": {
                    "type": "string"
                  },
                  "state": {
                    "type": "string",
                    "description": "The two-letter state or province code."
                  },
                  "zip": {
                    "type": "string",
                    "description": "The ZIP or postal code."
                  },
                  "country": {
                    "type": "string",
                    "description": "`US` or `CA`."
                  }
                },
                "required": [
                  "street",
                  "city",
                  "state",
                  "zip",
                  "country"
                ],
                "description": "The address emergency services are sent to. A field the stored address lacks is an empty string."
              }
            },
            "required": [
              "status",
              "address"
            ],
            "description": "The number's emergency (E911) registration. `null` when none was ever made."
          },
          "ratePerMinute": {
            "$ref": "#/components/schemas/VoiceNumberRates"
          }
        },
        "required": [
          "id",
          "object",
          "phoneNumber",
          "phoneNumberType",
          "countryCode",
          "isDefault",
          "voiceEnabled",
          "voiceMode",
          "agentId",
          "emergencyAddress",
          "ratePerMinute"
        ],
        "description": "One of the workspace's active phone numbers, and how it handles calls."
      },
      "VoiceNumberList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VoiceNumber"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "VoiceNumberRates": {
        "type": "object",
        "properties": {
          "inbound": {
            "type": "integer",
            "description": "Credits per started minute for a call to this number answered in the dashboard."
          },
          "outbound": {
            "type": "integer",
            "description": "Credits per started minute for a call placed from this number."
          },
          "agent": {
            "type": "integer",
            "description": "Credits per started minute for a call to this number answered by an agent."
          }
        },
        "required": [
          "inbound",
          "outbound",
          "agent"
        ],
        "description": "Per-minute prices in credits for this number, after any enterprise rate overrides. Every started minute is charged."
      },
      "VoicePreset": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "A voice from `GET /api/v1/voice/voices`. An agent whose stored voice is no longer offered reports `ashley`, the default. Known values: `ashley`, `edward`, `olivia`, `jacqueline`, `diego`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "ashley",
              "edward",
              "olivia",
              "jacqueline",
              "diego"
            ]
          },
          "label": {
            "type": "string",
            "description": "The voice's display name."
          },
          "language": {
            "type": "string",
            "description": "The language the voice speaks. Known values: `en`, `es`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "en",
              "es"
            ]
          }
        },
        "required": [
          "id",
          "label",
          "language"
        ],
        "description": "A voice an agent can speak with."
      },
      "VoicePresetList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VoicePreset"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The webhook's id."
          },
          "url": {
            "type": "string",
            "description": "The URL deliveries are posted to."
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A webhook event type. Known values: `message.sent`, `message.delivered`, `message.read`, `message.failed`, `message.bounced`, `message.retrying`, `message.received`, `message.opt_out`, `message.opt_in`, `verification.created`, `verification.delivered`, `verification.verified`, `verification.expired`, `verification.failed`, `verification.resent`, `verification.delivery_failed`, `conversation.created`, `conversation.updated`, `draft.created`, `draft.approved`, `draft.rejected`, `contact.auto_flagged`, `contact.marked_valid`, `contacts.lookup_completed`, `contacts.bulk_marked_valid`, `brand.verified`, `brand.failed`, `campaign.approved`, `campaign.rejected`, `campaign.suspended`, `assignment.confirmed`, `assignment.failed`, `rcs_brand.verified`, `rcs_brand.failed`, `rcs_agent.testing`, `rcs_agent.live`, `rcs_agent.rejected`, `rcs_agent.action_required`, `port.completed`, `port_out.requested`, `port_out.completed`, `port_out.rejected`, `port_out.cancelled`, `number.activated`, `number.failed`, `number.requirements_required`, `number.released`, `whatsapp_account.connected`, `whatsapp_account.failed`, `whatsapp_template.approved`, `whatsapp_template.rejected`, `whatsapp_template.paused`, `call.started`, `call.completed`, `call.recording.ready`, `short_code.action_required`, `short_code.rejected`, `short_code.filed`, `short_code.live`, `short_code.suspended`, `short_code.reactivated`, `short_code.cancelled`, `short_code.payment_succeeded`, `short_code.payment_failed`. More can be added at any time, so treat an unknown value as valid.",
              "x-sendly-extensible-enum": [
                "message.sent",
                "message.delivered",
                "message.read",
                "message.failed",
                "message.bounced",
                "message.retrying",
                "message.received",
                "message.opt_out",
                "message.opt_in",
                "verification.created",
                "verification.delivered",
                "verification.verified",
                "verification.expired",
                "verification.failed",
                "verification.resent",
                "verification.delivery_failed",
                "conversation.created",
                "conversation.updated",
                "draft.created",
                "draft.approved",
                "draft.rejected",
                "contact.auto_flagged",
                "contact.marked_valid",
                "contacts.lookup_completed",
                "contacts.bulk_marked_valid",
                "brand.verified",
                "brand.failed",
                "campaign.approved",
                "campaign.rejected",
                "campaign.suspended",
                "assignment.confirmed",
                "assignment.failed",
                "rcs_brand.verified",
                "rcs_brand.failed",
                "rcs_agent.testing",
                "rcs_agent.live",
                "rcs_agent.rejected",
                "rcs_agent.action_required",
                "port.completed",
                "port_out.requested",
                "port_out.completed",
                "port_out.rejected",
                "port_out.cancelled",
                "number.activated",
                "number.failed",
                "number.requirements_required",
                "number.released",
                "whatsapp_account.connected",
                "whatsapp_account.failed",
                "whatsapp_template.approved",
                "whatsapp_template.rejected",
                "whatsapp_template.paused",
                "call.started",
                "call.completed",
                "call.recording.ready",
                "short_code.action_required",
                "short_code.rejected",
                "short_code.filed",
                "short_code.live",
                "short_code.suspended",
                "short_code.reactivated",
                "short_code.cancelled",
                "short_code.payment_succeeded",
                "short_code.payment_failed"
              ]
            },
            "description": "The events it is subscribed to."
          },
          "description": {
            "type": "string",
            "description": "Present only when the webhook has a description."
          },
          "mode": {
            "type": "string",
            "description": "Which events the webhook receives: `all`, `test` (sandbox events only) or `live` (live events only). A `PATCH` with a falsy `mode` that is not a string, such as `0` or `false`, skips the check and is stored and returned as text. Known values: `all`, `test`, `live`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "all",
              "test",
              "live"
            ]
          },
          "is_active": {
            "type": "boolean",
            "description": "Whether deliveries are sent. While it is `false`, new events are neither sent nor recorded, and queued retries end as failed or cancelled."
          },
          "failure_count": {
            "type": "integer",
            "description": "Failed deliveries in the current failure streak."
          },
          "last_failure_at": {
            "type": "string",
            "format": "date-time",
            "description": "Absent when no delivery has failed since the circuit was reset."
          },
          "circuit_state": {
            "type": "string",
            "description": "The circuit breaker. It opens after 10 counted failures (timeouts, connection errors and 5xx answers; a 4xx does not count), each within a minute of the one before. While it is open, deliveries are not sent: each is recorded with the error code `circuit_open`, and is either scheduled to retry after the five-minute cool-down or left failed for `redeliver`. Once the cool-down has passed, the next delivery is sent as a probe and the circuit is `half_open`: a success closes it, and a counted failure opens it again. Known values: `closed`, `open`, `half_open`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "closed",
              "open",
              "half_open"
            ]
          },
          "circuit_opened_at": {
            "type": "string",
            "format": "date-time",
            "description": "Present only while the circuit has an opening time."
          },
          "api_version": {
            "type": "string",
            "description": "The payload version deliveries use, such as `2024-01`."
          },
          "metadata": {
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": {}
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ],
            "description": "Your own JSON value, as stored: an object unless you sent another JSON value. `{}` when none was set, or when it was `null`, `false`, `0` or an empty string."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the webhook was created. ISO 8601, in UTC."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the webhook last changed. ISO 8601, in UTC."
          },
          "total_deliveries": {
            "type": "integer",
            "description": "How many deliveries the webhook has. Only `GET /api/v1/webhooks` counts them; every other response says 0."
          },
          "successful_deliveries": {
            "type": "integer",
            "description": "How many of them were delivered. Only `GET /api/v1/webhooks` counts them; every other response says 0."
          },
          "success_rate": {
            "type": "integer",
            "description": "The delivered share, as a whole percentage from 0 to 100. Only `GET /api/v1/webhooks` computes it; every other response says 0."
          },
          "last_delivery_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the newest delivery was created. Only `GET /api/v1/webhooks` reads it; every other response says `null`."
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "mode",
          "is_active",
          "failure_count",
          "circuit_state",
          "api_version",
          "metadata",
          "created_at",
          "updated_at",
          "total_deliveries",
          "successful_deliveries",
          "success_rate",
          "last_delivery_at"
        ],
        "description": "A webhook endpoint. Its signing secret is never returned."
      },
      "WebhookBackfillResult": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "`Synthesized <n> missed webhook deliveries`, or `No missed events found in the given window`."
          },
          "run_id": {
            "type": "string",
            "description": "This run's id, `recover_...`."
          },
          "synthesized": {
            "type": "integer",
            "description": "How many events were rebuilt and sent or queued."
          },
          "by_type": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "How many were rebuilt, by event type."
          },
          "truncated": {
            "type": "boolean",
            "description": "Whether more events were missing than `limit`."
          },
          "candidates_scanned": {
            "type": "integer",
            "description": "How many messages were checked."
          },
          "delivery_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The new deliveries."
          },
          "since": {
            "type": "string",
            "format": "date-time",
            "description": "The window's start. ISO 8601, in UTC."
          },
          "until": {
            "type": "string",
            "format": "date-time",
            "description": "The window's end. ISO 8601, in UTC."
          },
          "limit": {
            "type": "integer",
            "description": "The limit used."
          }
        },
        "required": [
          "message",
          "run_id",
          "synthesized",
          "by_type",
          "truncated",
          "candidates_scanned",
          "delivery_ids",
          "since",
          "until",
          "limit"
        ]
      },
      "WebhookCircuitReset": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "enum": [
              "Circuit is already closed",
              "Circuit breaker reset"
            ]
          },
          "webhook": {
            "$ref": "#/components/schemas/Webhook"
          }
        },
        "required": [
          "message",
          "webhook"
        ]
      },
      "WebhookCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "properties": {
              "secret": {
                "type": "string",
                "description": "The signing secret, `whsec_` and 64 hex characters. Shown only this once."
              }
            },
            "required": [
              "secret"
            ]
          }
        ],
        "description": "A new webhook, with its signing secret."
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery's id."
          },
          "webhook_id": {
            "type": "string",
            "description": "The webhook's id."
          },
          "event_id": {
            "type": "string",
            "description": "The event's id, which a redelivery keeps, so you can dedupe on it. `evt_...` for a message event."
          },
          "event_type": {
            "type": "string",
            "description": "The event the delivery carried. `webhook.test` is the event `POST /api/v1/webhooks/{id}/test` sends. Known values: `message.sent`, `message.delivered`, `message.read`, `message.failed`, `message.bounced`, `message.retrying`, `message.received`, `message.opt_out`, `message.opt_in`, `verification.created`, `verification.delivered`, `verification.verified`, `verification.expired`, `verification.failed`, `verification.resent`, `verification.delivery_failed`, `conversation.created`, `conversation.updated`, `draft.created`, `draft.approved`, `draft.rejected`, `contact.auto_flagged`, `contact.marked_valid`, `contacts.lookup_completed`, `contacts.bulk_marked_valid`, `brand.verified`, `brand.failed`, `campaign.approved`, `campaign.rejected`, `campaign.suspended`, `assignment.confirmed`, `assignment.failed`, `rcs_brand.verified`, `rcs_brand.failed`, `rcs_agent.testing`, `rcs_agent.live`, `rcs_agent.rejected`, `rcs_agent.action_required`, `port.completed`, `port_out.requested`, `port_out.completed`, `port_out.rejected`, `port_out.cancelled`, `number.activated`, `number.failed`, `number.requirements_required`, `number.released`, `whatsapp_account.connected`, `whatsapp_account.failed`, `whatsapp_template.approved`, `whatsapp_template.rejected`, `whatsapp_template.paused`, `call.started`, `call.completed`, `call.recording.ready`, `short_code.action_required`, `short_code.rejected`, `short_code.filed`, `short_code.live`, `short_code.suspended`, `short_code.reactivated`, `short_code.cancelled`, `short_code.payment_succeeded`, `short_code.payment_failed`, `webhook.test`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "message.sent",
              "message.delivered",
              "message.read",
              "message.failed",
              "message.bounced",
              "message.retrying",
              "message.received",
              "message.opt_out",
              "message.opt_in",
              "verification.created",
              "verification.delivered",
              "verification.verified",
              "verification.expired",
              "verification.failed",
              "verification.resent",
              "verification.delivery_failed",
              "conversation.created",
              "conversation.updated",
              "draft.created",
              "draft.approved",
              "draft.rejected",
              "contact.auto_flagged",
              "contact.marked_valid",
              "contacts.lookup_completed",
              "contacts.bulk_marked_valid",
              "brand.verified",
              "brand.failed",
              "campaign.approved",
              "campaign.rejected",
              "campaign.suspended",
              "assignment.confirmed",
              "assignment.failed",
              "rcs_brand.verified",
              "rcs_brand.failed",
              "rcs_agent.testing",
              "rcs_agent.live",
              "rcs_agent.rejected",
              "rcs_agent.action_required",
              "port.completed",
              "port_out.requested",
              "port_out.completed",
              "port_out.rejected",
              "port_out.cancelled",
              "number.activated",
              "number.failed",
              "number.requirements_required",
              "number.released",
              "whatsapp_account.connected",
              "whatsapp_account.failed",
              "whatsapp_template.approved",
              "whatsapp_template.rejected",
              "whatsapp_template.paused",
              "call.started",
              "call.completed",
              "call.recording.ready",
              "short_code.action_required",
              "short_code.rejected",
              "short_code.filed",
              "short_code.live",
              "short_code.suspended",
              "short_code.reactivated",
              "short_code.cancelled",
              "short_code.payment_succeeded",
              "short_code.payment_failed",
              "webhook.test"
            ]
          },
          "status": {
            "type": "string",
            "description": "Where the delivery is: `pending` while it is queued or waiting for a retry. Known values: `pending`, `delivered`, `failed`, `cancelled`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "pending",
              "delivered",
              "failed",
              "cancelled"
            ]
          },
          "success": {
            "type": "boolean",
            "description": "Whether `status` is `delivered`."
          },
          "response_status_code": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The HTTP status your endpoint answered, when it answered."
          },
          "http_status": {
            "type": "integer",
            "description": "Same as `response_status_code`, or 0."
          },
          "response_time": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How long your endpoint took, in milliseconds."
          },
          "response_time_ms": {
            "type": "integer",
            "description": "Same as `response_time`, or 0."
          },
          "response_body": {
            "type": [
              "string",
              "null"
            ],
            "description": "What your endpoint answered, up to 10,000 characters."
          },
          "error_message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the attempt failed."
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the attempt failed, as a code. Known values: `timeout`, `connection_error`, `invalid_response`, `http_error`, `ssrf_blocked`, `circuit_open`, `max_retries_exceeded`, `webhook_disabled`, `invalid_url`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "timeout",
              "connection_error",
              "invalid_response",
              "http_error",
              "ssrf_blocked",
              "circuit_open",
              "max_retries_exceeded",
              "webhook_disabled",
              "invalid_url"
            ]
          },
          "attempt_number": {
            "type": "integer",
            "description": "Which attempt this is, starting at 1."
          },
          "max_attempts": {
            "type": "integer",
            "description": "How many attempts it gets: 1 for the delivery `POST /api/v1/webhooks/{id}/test` records, otherwise 6."
          },
          "next_retry_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the next attempt is due. ISO 8601, in UTC."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the delivery was created. ISO 8601, in UTC."
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When your endpoint accepted it. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "webhook_id",
          "event_id",
          "event_type",
          "status",
          "success",
          "response_status_code",
          "http_status",
          "response_time",
          "response_time_ms",
          "response_body",
          "error_message",
          "error_code",
          "attempt_number",
          "max_attempts",
          "next_retry_at",
          "created_at",
          "delivered_at"
        ],
        "description": "One delivery of one event to a webhook."
      },
      "WebhookDeliveryList": {
        "type": "object",
        "properties": {
          "deliveries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/LimitOffsetPagination"
          }
        },
        "required": [
          "deliveries",
          "pagination"
        ]
      },
      "WebhookDeliveryResult": {
        "type": "object",
        "properties": {
          "delivery": {
            "$ref": "#/components/schemas/WebhookDelivery"
          }
        },
        "required": [
          "delivery"
        ],
        "description": "One delivery."
      },
      "WebhookDeliveryRetry": {
        "type": "object",
        "properties": {
          "delivery": {
            "$ref": "#/components/schemas/WebhookDelivery"
          },
          "requeued": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "delivery",
          "requeued"
        ],
        "description": "The delivery the retry sent. For a message event (an `evt_...` event id) it is the same delivery row, sent again; for any other event, such as a test event, it is a new row with attempt 1 and 6 attempts. `pending` while it is queued, otherwise the result of the attempt."
      },
      "WebhookEventTypeList": {
        "type": "object",
        "properties": {
          "events": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "A webhook event type. Known values: `message.sent`, `message.delivered`, `message.read`, `message.failed`, `message.bounced`, `message.retrying`, `message.received`, `message.opt_out`, `message.opt_in`, `verification.created`, `verification.delivered`, `verification.verified`, `verification.expired`, `verification.failed`, `verification.resent`, `verification.delivery_failed`, `conversation.created`, `conversation.updated`, `draft.created`, `draft.approved`, `draft.rejected`, `contact.auto_flagged`, `contact.marked_valid`, `contacts.lookup_completed`, `contacts.bulk_marked_valid`, `brand.verified`, `brand.failed`, `campaign.approved`, `campaign.rejected`, `campaign.suspended`, `assignment.confirmed`, `assignment.failed`, `rcs_brand.verified`, `rcs_brand.failed`, `rcs_agent.testing`, `rcs_agent.live`, `rcs_agent.rejected`, `rcs_agent.action_required`, `port.completed`, `port_out.requested`, `port_out.completed`, `port_out.rejected`, `port_out.cancelled`, `number.activated`, `number.failed`, `number.requirements_required`, `number.released`, `whatsapp_account.connected`, `whatsapp_account.failed`, `whatsapp_template.approved`, `whatsapp_template.rejected`, `whatsapp_template.paused`, `call.started`, `call.completed`, `call.recording.ready`, `short_code.action_required`, `short_code.rejected`, `short_code.filed`, `short_code.live`, `short_code.suspended`, `short_code.reactivated`, `short_code.cancelled`, `short_code.payment_succeeded`, `short_code.payment_failed`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "message.sent",
                    "message.delivered",
                    "message.read",
                    "message.failed",
                    "message.bounced",
                    "message.retrying",
                    "message.received",
                    "message.opt_out",
                    "message.opt_in",
                    "verification.created",
                    "verification.delivered",
                    "verification.verified",
                    "verification.expired",
                    "verification.failed",
                    "verification.resent",
                    "verification.delivery_failed",
                    "conversation.created",
                    "conversation.updated",
                    "draft.created",
                    "draft.approved",
                    "draft.rejected",
                    "contact.auto_flagged",
                    "contact.marked_valid",
                    "contacts.lookup_completed",
                    "contacts.bulk_marked_valid",
                    "brand.verified",
                    "brand.failed",
                    "campaign.approved",
                    "campaign.rejected",
                    "campaign.suspended",
                    "assignment.confirmed",
                    "assignment.failed",
                    "rcs_brand.verified",
                    "rcs_brand.failed",
                    "rcs_agent.testing",
                    "rcs_agent.live",
                    "rcs_agent.rejected",
                    "rcs_agent.action_required",
                    "port.completed",
                    "port_out.requested",
                    "port_out.completed",
                    "port_out.rejected",
                    "port_out.cancelled",
                    "number.activated",
                    "number.failed",
                    "number.requirements_required",
                    "number.released",
                    "whatsapp_account.connected",
                    "whatsapp_account.failed",
                    "whatsapp_template.approved",
                    "whatsapp_template.rejected",
                    "whatsapp_template.paused",
                    "call.started",
                    "call.completed",
                    "call.recording.ready",
                    "short_code.action_required",
                    "short_code.rejected",
                    "short_code.filed",
                    "short_code.live",
                    "short_code.suspended",
                    "short_code.reactivated",
                    "short_code.cancelled",
                    "short_code.payment_succeeded",
                    "short_code.payment_failed"
                  ]
                },
                "description": {
                  "type": "string",
                  "description": "What the event reports."
                }
              },
              "required": [
                "type",
                "description"
              ]
            }
          }
        },
        "required": [
          "events"
        ]
      },
      "WebhookHttpsRequiredError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_url"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "invalid_url: not https",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "invalid_url"
        ]
      },
      "WebhookList": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/Webhook"
        }
      },
      "WebhookRecoveryPreview": {
        "type": "object",
        "properties": {
          "circuitState": {
            "type": "string",
            "description": "The circuit breaker. It opens after 10 counted failures (timeouts, connection errors and 5xx answers; a 4xx does not count), each within a minute of the one before. While it is open, deliveries are not sent: each is recorded with the error code `circuit_open`, and is either scheduled to retry after the five-minute cool-down or left failed for `redeliver`. Once the cool-down has passed, the next delivery is sent as a probe and the circuit is `half_open`: a success closes it, and a counted failure opens it again. Known values: `closed`, `open`, `half_open`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "closed",
              "open",
              "half_open"
            ]
          },
          "circuitOpenedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the circuit opened. ISO 8601, in UTC."
          },
          "failureCount": {
            "type": "integer",
            "description": "Failed deliveries in the current streak."
          },
          "auditFailures": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              },
              "byStatus": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "byEventType": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                }
              }
            },
            "required": [
              "total",
              "byStatus",
              "byEventType"
            ],
            "description": "Failed and cancelled deliveries created in the window: what `redeliver` would send."
          },
          "missingFromMessages": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              },
              "byEventType": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                }
              }
            },
            "required": [
              "total",
              "byEventType"
            ],
            "description": "Message events with no delivery in the window: what `backfill` would send."
          },
          "histogram": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "bucket": {
                  "type": "string",
                  "format": "date-time",
                  "description": "The bucket's start. ISO 8601, in UTC."
                },
                "missing": {
                  "type": "integer"
                },
                "failed": {
                  "type": "integer"
                }
              },
              "required": [
                "bucket",
                "missing",
                "failed"
              ]
            },
            "description": "The window in up to 24 equal buckets, oldest first."
          },
          "samples": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The event's object id, such as a message id."
                },
                "toMasked": {
                  "type": "string",
                  "description": "The recipient, masked, or `***` when there is none."
                },
                "eventType": {
                  "type": "string",
                  "description": "The event the delivery carried. `webhook.test` is the event `POST /api/v1/webhooks/{id}/test` sends. Known values: `message.sent`, `message.delivered`, `message.read`, `message.failed`, `message.bounced`, `message.retrying`, `message.received`, `message.opt_out`, `message.opt_in`, `verification.created`, `verification.delivered`, `verification.verified`, `verification.expired`, `verification.failed`, `verification.resent`, `verification.delivery_failed`, `conversation.created`, `conversation.updated`, `draft.created`, `draft.approved`, `draft.rejected`, `contact.auto_flagged`, `contact.marked_valid`, `contacts.lookup_completed`, `contacts.bulk_marked_valid`, `brand.verified`, `brand.failed`, `campaign.approved`, `campaign.rejected`, `campaign.suspended`, `assignment.confirmed`, `assignment.failed`, `rcs_brand.verified`, `rcs_brand.failed`, `rcs_agent.testing`, `rcs_agent.live`, `rcs_agent.rejected`, `rcs_agent.action_required`, `port.completed`, `port_out.requested`, `port_out.completed`, `port_out.rejected`, `port_out.cancelled`, `number.activated`, `number.failed`, `number.requirements_required`, `number.released`, `whatsapp_account.connected`, `whatsapp_account.failed`, `whatsapp_template.approved`, `whatsapp_template.rejected`, `whatsapp_template.paused`, `call.started`, `call.completed`, `call.recording.ready`, `short_code.action_required`, `short_code.rejected`, `short_code.filed`, `short_code.live`, `short_code.suspended`, `short_code.reactivated`, `short_code.cancelled`, `short_code.payment_succeeded`, `short_code.payment_failed`, `webhook.test`. More can be added at any time, so treat an unknown value as valid.",
                  "x-sendly-extensible-enum": [
                    "message.sent",
                    "message.delivered",
                    "message.read",
                    "message.failed",
                    "message.bounced",
                    "message.retrying",
                    "message.received",
                    "message.opt_out",
                    "message.opt_in",
                    "verification.created",
                    "verification.delivered",
                    "verification.verified",
                    "verification.expired",
                    "verification.failed",
                    "verification.resent",
                    "verification.delivery_failed",
                    "conversation.created",
                    "conversation.updated",
                    "draft.created",
                    "draft.approved",
                    "draft.rejected",
                    "contact.auto_flagged",
                    "contact.marked_valid",
                    "contacts.lookup_completed",
                    "contacts.bulk_marked_valid",
                    "brand.verified",
                    "brand.failed",
                    "campaign.approved",
                    "campaign.rejected",
                    "campaign.suspended",
                    "assignment.confirmed",
                    "assignment.failed",
                    "rcs_brand.verified",
                    "rcs_brand.failed",
                    "rcs_agent.testing",
                    "rcs_agent.live",
                    "rcs_agent.rejected",
                    "rcs_agent.action_required",
                    "port.completed",
                    "port_out.requested",
                    "port_out.completed",
                    "port_out.rejected",
                    "port_out.cancelled",
                    "number.activated",
                    "number.failed",
                    "number.requirements_required",
                    "number.released",
                    "whatsapp_account.connected",
                    "whatsapp_account.failed",
                    "whatsapp_template.approved",
                    "whatsapp_template.rejected",
                    "whatsapp_template.paused",
                    "call.started",
                    "call.completed",
                    "call.recording.ready",
                    "short_code.action_required",
                    "short_code.rejected",
                    "short_code.filed",
                    "short_code.live",
                    "short_code.suspended",
                    "short_code.reactivated",
                    "short_code.cancelled",
                    "short_code.payment_succeeded",
                    "short_code.payment_failed",
                    "webhook.test"
                  ]
                },
                "occurredAt": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the delivery or message was created. ISO 8601, in UTC."
                }
              },
              "required": [
                "id",
                "toMasked",
                "eventType",
                "occurredAt"
              ]
            },
            "description": "Up to 5 affected events: failed deliveries first, then missing message events, each newest first. A failed delivery whose payload has no `data.object.id`, such as an opt-out event, is left out; a test event's is `test_msg_...`."
          },
          "windowSuggestion": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "since": {
                "type": "string",
                "format": "date-time",
                "description": "When the circuit opened. ISO 8601, in UTC."
              },
              "until": {
                "type": "string",
                "format": "date-time",
                "description": "Now. ISO 8601, in UTC."
              }
            },
            "required": [
              "since",
              "until"
            ],
            "description": "The outage window, when the circuit has an opening time."
          },
          "since": {
            "type": "string",
            "format": "date-time",
            "description": "The window's start. ISO 8601, in UTC."
          },
          "until": {
            "type": "string",
            "format": "date-time",
            "description": "The window's end. ISO 8601, in UTC."
          }
        },
        "required": [
          "circuitState",
          "circuitOpenedAt",
          "failureCount",
          "auditFailures",
          "missingFromMessages",
          "histogram",
          "samples",
          "windowSuggestion",
          "since",
          "until"
        ],
        "description": "What a recovery would do. Its keys are camelCase, unlike the other webhook responses."
      },
      "WebhookRedeliverResult": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "`Requeued <n> webhook deliveries`, `Requeued 1 webhook delivery` when there is one, or `No deliveries matched the given window`."
          },
          "run_id": {
            "type": "string",
            "description": "This run's id, `recover_...`."
          },
          "requeued": {
            "type": "integer",
            "description": "How many deliveries were sent again or queued."
          },
          "skipped": {
            "type": "integer",
            "description": "How many could not be requeued."
          },
          "truncated": {
            "type": "boolean",
            "description": "Whether more deliveries matched than `limit`."
          },
          "window_size": {
            "type": "integer",
            "description": "How many deliveries matched, up to `limit` plus one."
          },
          "delivery_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The requeued deliveries."
          },
          "since": {
            "type": "string",
            "format": "date-time",
            "description": "The window's start. ISO 8601, in UTC."
          },
          "until": {
            "type": "string",
            "format": "date-time",
            "description": "The window's end. ISO 8601, in UTC."
          },
          "limit": {
            "type": "integer",
            "description": "The limit used."
          }
        },
        "required": [
          "message",
          "run_id",
          "requeued",
          "skipped",
          "truncated",
          "window_size",
          "delivery_ids",
          "since",
          "until",
          "limit"
        ]
      },
      "WebhookSecretRotation": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "id": {
            "type": "string",
            "description": "The webhook's id."
          },
          "secret": {
            "type": "string",
            "description": "The new signing secret, `whsec_` and 64 hex characters."
          },
          "new_secret": {
            "type": "string",
            "description": "Same as `secret`."
          },
          "new_secret_version": {
            "type": "integer",
            "description": "The webhook's new secret version: one more than before."
          },
          "grace_period_hours": {
            "type": "number",
            "enum": [
              0
            ],
            "description": "Always 0: the previous secret stops working at once."
          },
          "rotated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the secret was rotated. ISO 8601, in UTC."
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "id",
          "secret",
          "new_secret",
          "new_secret_version",
          "grace_period_hours",
          "rotated_at",
          "message"
        ]
      },
      "WebhookTestResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "message": {
            "type": "string",
            "description": "`Test webhook delivered successfully in <n>ms`."
          },
          "delivery": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The test delivery's id."
              },
              "delivery_id": {
                "type": "string",
                "description": "Same as `id`."
              },
              "webhook_url": {
                "type": "string",
                "description": "The URL the event was posted to."
              },
              "event_type": {
                "type": "string",
                "enum": [
                  "webhook.test"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "delivered"
                ]
              },
              "response_time": {
                "type": "integer",
                "description": "How long your endpoint took, in milliseconds."
              },
              "status_code": {
                "type": "integer",
                "description": "The 2xx status your endpoint answered."
              },
              "response_body": {
                "type": "string",
                "description": "What your endpoint answered, up to 500 characters."
              },
              "delivered_at": {
                "type": "string",
                "format": "date-time",
                "description": "When the test event was delivered. ISO 8601, in UTC."
              }
            },
            "required": [
              "id",
              "delivery_id",
              "webhook_url",
              "event_type",
              "status",
              "response_time",
              "status_code",
              "response_body",
              "delivered_at"
            ]
          }
        },
        "required": [
          "success",
          "message",
          "delivery"
        ],
        "description": "Your endpoint accepted the test event."
      },
      "WhatsAppCallingSettings": {
        "type": "object",
        "properties": {
          "phoneNumber": {
            "type": "string",
            "description": "The sender, in E.164 format."
          },
          "callingEnabled": {
            "type": "boolean",
            "description": "Whether WhatsApp calling is now on."
          },
          "outboundCallingAllowed": {
            "type": "boolean",
            "description": "Whether WhatsApp lets the business place calls from this number: `false` for +1, +20, +84 and +234 numbers."
          }
        },
        "required": [
          "phoneNumber",
          "callingEnabled",
          "outboundCallingAllowed"
        ]
      },
      "WhatsAppConversationalComponents": {
        "type": "object",
        "properties": {
          "phoneNumber": {
            "type": "string",
            "description": "The sender, in E.164 format."
          },
          "iceBreakers": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Up to 4 suggestions shown when someone first opens a chat with the business."
          },
          "commands": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "description": "Letters, digits or underscores, 1 to 32 characters, with no leading `/`."
                },
                "description": {
                  "type": "string",
                  "description": "What the command does."
                }
              },
              "required": [
                "command",
                "description"
              ]
            },
            "description": "Up to 30 commands shown when the customer types \"/\"."
          }
        },
        "required": [
          "phoneNumber",
          "iceBreakers",
          "commands"
        ]
      },
      "WhatsAppLiveKeyRequiredError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "whatsapp_requires_live_key"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "whatsapp_requires_live_key",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "whatsapp_requires_live_key"
        ]
      },
      "WhatsAppProfilePhotoTooLargeError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "whatsapp_profile_photo_too_large"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "whatsapp_profile_photo_too_large",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "whatsapp_profile_photo_too_large"
        ]
      },
      "WhatsAppProfileUpdateFailedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "whatsapp_profile_update_failed"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "whatsapp_profile_update_failed",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "whatsapp_profile_update_failed"
        ]
      },
      "WhatsAppSendRecoveredResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "channel": {
            "type": "string",
            "enum": [
              "whatsapp"
            ]
          },
          "message_format": {
            "type": "string",
            "enum": [
              "whatsapp"
            ]
          },
          "messageFormat": {
            "type": "string",
            "enum": [
              "whatsapp"
            ]
          },
          "to": {
            "type": "string",
            "description": "The recipient, as sent."
          },
          "from": {
            "type": "string",
            "description": "The sender, as sent."
          },
          "status": {
            "type": "string",
            "enum": [
              "sent"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "outbound"
            ]
          },
          "segments": {
            "type": "number",
            "enum": [
              1
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The custom metadata stored with the message, as sent."
          }
        },
        "required": [
          "id",
          "channel",
          "message_format",
          "messageFormat",
          "to",
          "from",
          "status",
          "direction",
          "segments",
          "metadata"
        ],
        "description": "WhatsApp accepted the message, then recording it failed. The message is in flight and was charged.",
        "title": "WhatsApp message sent, partly recorded",
        "x-sendly-visibility": "preview"
      },
      "WhatsAppSendResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The message's id."
          },
          "channel": {
            "type": "string",
            "enum": [
              "whatsapp"
            ]
          },
          "message_format": {
            "type": "string",
            "enum": [
              "whatsapp"
            ]
          },
          "messageFormat": {
            "type": "string",
            "enum": [
              "whatsapp"
            ]
          },
          "to": {
            "type": "string",
            "description": "The recipient, in E.164 format."
          },
          "from": {
            "type": "string",
            "description": "The WhatsApp sender number."
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` for a template message."
          },
          "status": {
            "type": "string",
            "enum": [
              "sent",
              "failed"
            ],
            "description": "`sent`, or `failed` when WhatsApp couldn't take the message and it went as an SMS instead: see `fallback`."
          },
          "direction": {
            "type": "string",
            "enum": [
              "outbound"
            ]
          },
          "segments": {
            "type": "number",
            "enum": [
              1
            ]
          },
          "creditsUsed": {
            "type": "integer"
          },
          "whatsapp": {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "text",
                  "media",
                  "template"
                ]
              },
              "template": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string"
                  },
                  "category": {
                    "type": "string",
                    "description": "The category the template was billed as. Known values: `utility`, `authentication`, `marketing`. More can be added at any time, so treat an unknown value as valid.",
                    "x-sendly-extensible-enum": [
                      "utility",
                      "authentication",
                      "marketing"
                    ]
                  }
                },
                "required": [
                  "name",
                  "language",
                  "category"
                ]
              },
              "messageId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "WhatsApp's own message id, when it returned one."
              }
            },
            "required": [
              "kind",
              "messageId"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was created. ISO 8601, in UTC."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {},
            "description": "The custom metadata stored with the message, as sent."
          },
          "fallback": {
            "type": "object",
            "properties": {
              "channel": {
                "type": "string",
                "enum": [
                  "sms"
                ]
              },
              "status": {
                "type": "string",
                "description": "`pending` until WhatsApp's outcome is known; `sent` when the SMS went; `failed` when the SMS carrier refused it or credits ran out; `unavailable` when the SMS could no longer be sent from this number; `skipped` when the WhatsApp failure isn't one an SMS fixes, such as the recipient opting out. Known values: `pending`, `sent`, `failed`, `unavailable`, `skipped`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "pending",
                  "sent",
                  "failed",
                  "unavailable",
                  "skipped"
                ]
              },
              "reason": {
                "type": "string",
                "description": "What made the message fall back. Known values: `window_closed`, `whatsapp_refused`, `whatsapp_failed`. More can be added at any time, so treat an unknown value as valid.",
                "x-sendly-extensible-enum": [
                  "window_closed",
                  "whatsapp_refused",
                  "whatsapp_failed"
                ]
              },
              "messageId": {
                "type": "string",
                "description": "The SMS message's id, once it exists."
              },
              "creditsUsed": {
                "type": "integer",
                "description": "Credits charged for the SMS."
              },
              "error": {
                "type": "string",
                "description": "Why the SMS didn't go, in plain English."
              },
              "contentDropped": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Template parts with no SMS form, such as `quick_replies` or `header_media`."
              }
            },
            "required": [
              "channel",
              "status"
            ],
            "description": "The SMS fallback of a WhatsApp message sent with `fallbackToSms: true`."
          }
        },
        "required": [
          "id",
          "channel",
          "message_format",
          "messageFormat",
          "to",
          "from",
          "text",
          "status",
          "direction",
          "segments",
          "creditsUsed",
          "whatsapp",
          "createdAt",
          "metadata"
        ],
        "title": "WhatsApp message sent",
        "x-sendly-visibility": "preview"
      },
      "WhatsAppSender": {
        "type": "object",
        "properties": {
          "phoneNumber": {
            "type": "string",
            "description": "The sender, in E.164 format."
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The name recipients see, once WhatsApp has one."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "suspended"
            ],
            "description": "`pending` while the connection is in progress, `active` once the number can send, `suspended` when sending is suspended."
          },
          "qualityRating": {
            "type": [
              "string",
              "null"
            ],
            "description": "WhatsApp's quality rating, such as `GREEN`, once rated."
          },
          "businessAccountId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The WhatsApp Business account the number belongs to. `null` while `pending`. Pass it to `POST /api/v1/whatsapp/signup` to add another number to the same account."
          },
          "businessName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The account's business name. `null` while `pending`, or when none is on file."
          },
          "callingEnabled": {
            "type": "boolean",
            "description": "Whether WhatsApp calling is on."
          },
          "outboundCallingAllowed": {
            "type": "boolean",
            "description": "Whether WhatsApp lets the business place calls from this number: `false` for +1, +20, +84 and +234 numbers."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the connection began. ISO 8601, in UTC."
          }
        },
        "required": [
          "phoneNumber",
          "displayName",
          "status",
          "qualityRating",
          "businessAccountId",
          "businessName",
          "callingEnabled",
          "outboundCallingAllowed",
          "createdAt"
        ]
      },
      "WhatsAppSenderDisconnected": {
        "type": "object",
        "properties": {
          "phoneNumber": {
            "type": "string",
            "description": "The number, in E.164 format."
          },
          "disconnected": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "phoneNumber",
          "disconnected"
        ]
      },
      "WhatsAppSenderList": {
        "type": "object",
        "properties": {
          "senders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WhatsAppSender"
            }
          }
        },
        "required": [
          "senders"
        ]
      },
      "WhatsAppSenderNotConnectedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "whatsapp_sender_not_connected"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "whatsapp_sender_not_connected",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "whatsapp_sender_not_connected"
        ]
      },
      "WhatsAppSenderProfile": {
        "type": "object",
        "properties": {
          "phoneNumber": {
            "type": "string",
            "description": "The sender, in E.164 format."
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The business name recipients see."
          },
          "profilePhotoUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The profile photo's URL."
          },
          "category": {
            "type": [
              "string",
              "null"
            ],
            "description": "The business category."
          },
          "about": {
            "type": [
              "string",
              "null"
            ],
            "description": "The short profile line."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "The longer business description."
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "description": "The contact email on the profile."
          },
          "website": {
            "type": [
              "string",
              "null"
            ],
            "description": "The website on the profile."
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "The business address on the profile."
          }
        },
        "required": [
          "phoneNumber",
          "displayName",
          "profilePhotoUrl",
          "category",
          "about",
          "description",
          "email",
          "website",
          "address"
        ],
        "description": "A sender's business profile, as WhatsApp shows it. A field not set is `null`."
      },
      "WhatsAppSignup": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The signup's id."
          },
          "status": {
            "type": "string",
            "description": "Where the connection is: `initiated` until the connect page is finished, `registering` while WhatsApp sets the number up, `verifying` while a number added by code waits for its code, then `active` or `failed`. Known values: `initiated`, `registering`, `verifying`, `active`, `failed`, `expired`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "initiated",
              "registering",
              "verifying",
              "active",
              "failed",
              "expired"
            ]
          },
          "phoneNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "The number being connected, in E.164 format."
          },
          "businessAccountId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The WhatsApp Business account's id, while `verifying` and once `active`. `null` otherwise."
          },
          "failureReasons": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Why the signup failed, such as `signup_abandoned`, `setup_fee_payment_failed` or `cancelled_by_user`. `null` unless it failed. A failed signup's $9.99 connection fee is refunded."
          },
          "verificationMethod": {
            "type": "string",
            "enum": [
              "sms",
              "voice"
            ],
            "description": "How WhatsApp sends the code. Only while `verifying`."
          },
          "verificationAttemptsRemaining": {
            "type": "integer",
            "description": "Wrong codes that may still be sent. Only while `verifying`."
          },
          "verificationCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "The code WhatsApp texted to the number, read from its inbound messages, or `null` when none has arrived. Only from `GET /api/v1/whatsapp/signup/{id}`, while `verifying`."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the signup last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "status",
          "phoneNumber",
          "businessAccountId",
          "failureReasons",
          "updatedAt"
        ]
      },
      "WhatsAppSignupNotActiveError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "signup_not_active"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "signup_not_active",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "signup_not_active"
        ]
      },
      "WhatsAppSignupNotFoundError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "signup_not_found"
            ]
          }
        },
        "required": [
          "error"
        ],
        "description": "Only `error`, with no `message`.",
        "title": "signup_not_found",
        "x-sendly-error-shape": "bare",
        "x-sendly-error-codes": [
          "signup_not_found"
        ]
      },
      "WhatsAppSignupSession": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The signup's id."
          },
          "connectUrl": {
            "type": "string",
            "description": "The connect page. A person opens it in a browser and signs in with Facebook to link the WhatsApp Business account. It works for an hour."
          },
          "status": {
            "type": "string",
            "description": "Where the connection is: `initiated` until the connect page is finished, `registering` while WhatsApp sets the number up, `verifying` while a number added by code waits for its code, then `active` or `failed`. Known values: `initiated`, `registering`, `verifying`, `active`, `failed`, `expired`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "initiated",
              "registering",
              "verifying",
              "active",
              "failed",
              "expired"
            ]
          }
        },
        "required": [
          "id",
          "connectUrl",
          "status"
        ]
      },
      "WhatsAppTemplate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The template's id."
          },
          "name": {
            "type": "string"
          },
          "language": {
            "type": "string",
            "description": "The language code, such as `en_US`."
          },
          "category": {
            "type": "string",
            "description": "The template's category. WhatsApp may change it on review, and it sets the per-message price. Known values: `AUTHENTICATION`, `UTILITY`, `MARKETING`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "AUTHENTICATION",
              "UTILITY",
              "MARKETING"
            ]
          },
          "status": {
            "type": "string",
            "description": "The template's review status, as WhatsApp reports it, in upper case. Only an `APPROVED` template can be sent. Known values: `PENDING`, `APPROVED`, `REJECTED`, `PAUSED`, `DISABLED`. More can be added at any time, so treat an unknown value as valid.",
            "x-sendly-extensible-enum": [
              "PENDING",
              "APPROVED",
              "REJECTED",
              "PAUSED",
              "DISABLED"
            ]
          },
          "body": {
            "type": [
              "string",
              "null"
            ],
            "description": "The body text, with `{{1}}`-style variables. `null` when it has none."
          },
          "header": {
            "type": [
              "string",
              "null"
            ],
            "description": "The text header, if any."
          },
          "footer": {
            "type": [
              "string",
              "null"
            ],
            "description": "The footer, if any."
          },
          "examples": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Example values for the body variables, by number: `{\"1\": \"A1234\"}`."
          },
          "qualityRating": {
            "type": [
              "string",
              "null"
            ],
            "description": "WhatsApp's quality rating, once rated."
          },
          "rejectionReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why WhatsApp rejected it, when it did."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the template was created. ISO 8601, in UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the template last changed. ISO 8601, in UTC."
          }
        },
        "required": [
          "id",
          "name",
          "language",
          "category",
          "status",
          "body",
          "header",
          "footer",
          "examples",
          "qualityRating",
          "rejectionReason",
          "createdAt",
          "updatedAt"
        ],
        "description": "A WhatsApp message template. Its buttons are not returned."
      },
      "WhatsAppTemplateCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WhatsAppTemplate"
          },
          {
            "type": "object",
            "properties": {
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Why WhatsApp may reject it: the sender's display name is not approved yet, or a marketing template has no opt-out button. Present only when there is one."
              }
            }
          }
        ],
        "description": "A WhatsApp message template. Its buttons are not returned."
      },
      "WhatsAppTemplateDeleted": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The deleted template's id."
          },
          "deleted": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "id",
          "deleted"
        ]
      },
      "WhatsAppTemplateExistsError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "template_already_exists"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "template_already_exists",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "template_already_exists"
        ]
      },
      "WhatsAppTemplateList": {
        "type": "object",
        "properties": {
          "templates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WhatsAppTemplate"
            }
          }
        },
        "required": [
          "templates"
        ]
      },
      "WhatsAppTemplateNotFoundError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "template_not_found"
            ]
          }
        },
        "required": [
          "error"
        ],
        "description": "Only `error`, with no `message`.",
        "title": "template_not_found",
        "x-sendly-error-shape": "bare",
        "x-sendly-error-codes": [
          "template_not_found"
        ]
      },
      "WhatsAppTemplateRefusedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "template_refused"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "description": "`message` gives WhatsApp's reason. Sending the same template again gets the same answer.",
        "title": "template_refused",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "template_refused"
        ]
      },
      "WhatsAppTemplateRuleError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "template_name_invalid",
              "template_name_reserved_prefix",
              "template_category_invalid",
              "template_body_required",
              "template_header_variable_unsupported",
              "template_example_required",
              "template_authentication_no_links",
              "template_authentication_otp_button_required",
              "template_button_url_required",
              "template_button_type_unsupported",
              "template_body_too_long",
              "template_body_variable_at_edge",
              "template_footer_too_long",
              "template_too_many_buttons",
              "template_button_text_too_long"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "The template breaks a WhatsApp rule",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "template_name_invalid",
          "template_name_reserved_prefix",
          "template_category_invalid",
          "template_body_required",
          "template_header_variable_unsupported",
          "template_example_required",
          "template_authentication_no_links",
          "template_authentication_otp_button_required",
          "template_button_url_required",
          "template_button_type_unsupported",
          "template_body_too_long",
          "template_body_variable_at_edge",
          "template_footer_too_long",
          "template_too_many_buttons",
          "template_button_text_too_long"
        ]
      },
      "WhatsAppVerificationResendFailedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "whatsapp_verification_resend_failed"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "whatsapp_verification_resend_failed",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "whatsapp_verification_resend_failed"
        ]
      },
      "WhatsAppVerificationStartFailedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "whatsapp_verification_start_failed"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "whatsapp_verification_start_failed",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "whatsapp_verification_start_failed"
        ]
      },
      "WhatsAppWindow": {
        "type": "object",
        "properties": {
          "open": {
            "type": "boolean",
            "description": "Whether the window is open now."
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the window closes, or closed. `null` when Sendly has no window on record for the pair, which a send may still find open."
          }
        },
        "required": [
          "open",
          "expiresAt"
        ]
      },
      "WorkspaceNotFoundError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "workspace_not_found"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "workspace_not_found",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "workspace_not_found"
        ]
      },
      "WorkspaceNotOwnedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_workspace",
              "not_workspace_owner"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "invalid_workspace, not_workspace_owner",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "invalid_workspace",
          "not_workspace_owner"
        ]
      },
      "WorkspacePermissionError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "forbidden"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "forbidden",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "forbidden"
        ]
      },
      "WorkspaceRequiredError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "workspace_required"
            ]
          }
        },
        "required": [
          "error"
        ],
        "description": "Only `error`, with no `message`. The API key belongs to no workspace, as some keys made before workspaces do.",
        "title": "workspace_required",
        "x-sendly-error-shape": "bare",
        "x-sendly-error-codes": [
          "workspace_required"
        ]
      },
      "WorkspaceSuspendedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "workspace_suspended"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "workspace_suspended",
        "x-sendly-error-shape": "envelope",
        "x-sendly-error-codes": [
          "workspace_suspended"
        ]
      },
      "WorkspaceUpgradeCancelled": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "cancelled": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "cancelledVerificationId": {
            "type": "string",
            "description": "The pending verification that was removed."
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "cancelled",
          "cancelledVerificationId",
          "message"
        ],
        "title": "Upgrade cancelled"
      },
      "WorkspaceUpgradeDisposition": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "disposition": {
            "type": "string",
            "enum": [
              "moved",
              "released"
            ]
          },
          "supersededVerificationId": {
            "type": "string",
            "description": "The previous entity's verification."
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "disposition",
          "supersededVerificationId",
          "message"
        ]
      },
      "WorkspaceUpgradeDispositionRequest": {
        "type": "object",
        "properties": {
          "disposition": {
            "type": "string",
            "enum": [
              "moved",
              "released"
            ],
            "description": "`moved` keeps the previous number on another workspace you own; `released` gives it up."
          },
          "targetOrgId": {
            "type": "string",
            "description": "The workspace that keeps the number. Required for `moved`."
          }
        },
        "required": [
          "disposition"
        ]
      },
      "WorkspaceUpgradeNothingToCancel": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "cancelled": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "cancelled",
          "message"
        ],
        "title": "No upgrade to cancel"
      },
      "WorkspaceUpgradeResubmitted": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "pendingVerificationId": {
            "type": "string",
            "description": "The pending verification."
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "pendingVerificationId",
          "message"
        ]
      },
      "WorkspaceUpgradeStarted": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "pendingVerificationId": {
            "type": "string",
            "description": "The new entity's pending verification."
          },
          "status": {
            "type": "string",
            "enum": [
              "provisioning"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "pendingVerificationId",
          "status",
          "message"
        ]
      },
      "WorkspaceUpgradeStatus": {
        "type": "object",
        "properties": {
          "pending": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PendingWorkspaceUpgrade"
              },
              {
                "type": "null"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "pending"
        ],
        "description": "`pending` is the upgrade in flight, or `null` when there is none."
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_test_v1_... or sk_live_v1_...",
        "description": "An API key in the Authorization header: `Authorization: Bearer sk_test_v1_...`. Test keys simulate every send and never charge. A signed-in CLI session token (`cli_...`) is accepted too, and can pick a workspace with the `X-Organization-Id` header. An operation's `x-sendly-auth` says how it checks them: `apiKey` checks the scopes of the key or of the CLI session; `cliOrApiKey` checks an API key's scopes only, and accepts a signed-in dashboard session as well."
      }
    }
  },
  "x-sendly-errors": {
    "ACCOUNT_UNDER_REVIEW": {
      "description": "The account is under review, as after it sent text that reads like a scam. `error` holds a sentence: the code is in `code`.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "code"
      ]
    },
    "TRANSACTIONAL_MARKETING_MISMATCH": {
      "description": "A message marked transactional reads as marketing during quiet hours. The body has no `error`: the code is in `code`.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "code",
        "matchedKeywords",
        "reason",
        "suggestion"
      ]
    },
    "access_denied": {
      "description": "The caller may not reach this destination or resource.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "code",
        "countryCode",
        "countryName"
      ],
      "sentences": [
        "Access denied to this workspace",
        "Key does not belong to this workspace",
        "Page does not belong to this workspace"
      ]
    },
    "account_suspended": {
      "description": "The account is suspended.",
      "statuses": {
        "403": "final"
      }
    },
    "account_under_review": {
      "description": "The account is under review, as after it sent text that reads like a scam.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "code"
      ],
      "sentences": [
        "Your account has been flagged for review. Please contact support."
      ]
    },
    "active_verification_not_verified": {
      "description": "The workspace's current verification is not `verified` yet. `message` names its status as stored.",
      "statuses": {
        "400": "final"
      }
    },
    "agent_disabled": {
      "description": "The agent is switched off.",
      "statuses": {
        "409": "final"
      }
    },
    "agent_in_use": {
      "description": "`enabled` is `false` while numbers still send their calls to the agent. `numbers` lists them.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "numbers"
      ]
    },
    "agent_limit": {
      "description": "The workspace already has 20 agents.",
      "statuses": {
        "409": "final"
      }
    },
    "agent_not_found": {
      "description": "No agent with this id is in the workspace.",
      "statuses": {
        "404": "final"
      }
    },
    "agent_required": {
      "description": "`agentId` is missing or empty.",
      "statuses": {
        "400": "final"
      }
    },
    "agents_unavailable": {
      "description": "AI agents are not available on the platform right now.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "all_opted_out": {
      "description": "Every recipient opted out.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "optedOutCount"
      ]
    },
    "all_recipients_blocked": {
      "description": "Every recipient opted out or cannot receive texts. The campaign is now `failed`.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "invalidCount",
        "optedOutCount"
      ]
    },
    "already_claimed": {
      "description": "Another request or the scheduler started sending the campaign first.",
      "statuses": {
        "409": "final"
      }
    },
    "already_disposed": {
      "description": "A choice for the previous number after a business upgrade is already recorded.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "disposition"
      ]
    },
    "already_member": {
      "description": "Someone with that email is already a member.",
      "statuses": {
        "409": "final"
      },
      "sentences": [
        "User is already a member"
      ],
      "proposed": true
    },
    "already_owned": {
      "description": "The number already belongs to a workspace.",
      "statuses": {
        "409": "final"
      }
    },
    "already_revoked": {
      "description": "The API key is already revoked.",
      "statuses": {
        "409": "final"
      },
      "sentences": [
        "API key is already revoked"
      ],
      "proposed": true
    },
    "already_rotating": {
      "description": "The key is already being rotated, or was created to expire.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "expiresAt"
      ]
    },
    "already_short": {
      "description": "`url` is already a short link.",
      "statuses": {
        "400": "final"
      }
    },
    "already_submitted": {
      "description": "The request or the verification was already submitted.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "status"
      ],
      "sentences": [
        "Workspace already has a verification"
      ]
    },
    "ambiguous_campaign": {
      "description": "The workspace has more than one active 10DLC campaign, so the number cannot join one automatically.",
      "statuses": {
        "409": "final"
      }
    },
    "api_key_required": {
      "description": "A CLI session was used for an operation that needs an API key.",
      "statuses": {
        "401": "final"
      },
      "extra": [
        "hint"
      ]
    },
    "assignment_failed": {
      "description": "The number could not be assigned to the 10DLC campaign.",
      "statuses": {
        "400": "final",
        "500": "retry_same_key",
        "503": "retry_same_key"
      }
    },
    "auth_person_required": {
      "description": "`authPersonName` or `authPersonEmail` is missing or empty.",
      "statuses": {
        "400": "final"
      }
    },
    "authentication_failed": {
      "description": "Checking the credentials failed unexpectedly.",
      "statuses": {
        "401": "retry_same_key"
      },
      "sentences": [
        "Authentication failed"
      ],
      "proposed": true
    },
    "batch_too_large": {
      "description": "More than 10,000 recipients.",
      "statuses": {
        "400": "final"
      }
    },
    "body_too_large": {
      "description": "The body is larger than the server accepts.",
      "statuses": {
        "413": "final"
      },
      "proposed": true
    },
    "brand_create_failed": {
      "description": "The 10DLC brand could not be registered.",
      "statuses": {
        "400": "final",
        "500": "check_before_retry",
        "503": "check_before_retry"
      }
    },
    "brand_not_registered": {
      "description": "The campaign's brand is not registered.",
      "statuses": {
        "409": "final"
      }
    },
    "brand_not_verified": {
      "description": "The brand is registered but not verified yet.",
      "statuses": {
        "400": "final",
        "409": "final"
      }
    },
    "business_verification_required": {
      "description": "The workspace needs an approved business verification first.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "verificationUrl"
      ]
    },
    "buy_failed": {
      "description": "The purchase failed unexpectedly. A US local purchase that fails here was not charged.",
      "statuses": {
        "500": "check_before_retry"
      }
    },
    "ca_local_only": {
      "description": "A Canadian number whose `phoneNumberType` is not `local`.",
      "statuses": {
        "400": "final"
      }
    },
    "call_not_found": {
      "description": "No call with this id is in the key's workspace.",
      "statuses": {
        "404": "final"
      }
    },
    "campaign_create_failed": {
      "description": "The 10DLC campaign could not be registered.",
      "statuses": {
        "400": "final",
        "500": "check_before_retry",
        "503": "check_before_retry"
      }
    },
    "campaign_not_active": {
      "description": "The 10DLC campaign is not active.",
      "statuses": {
        "400": "final",
        "409": "final"
      }
    },
    "campaign_not_found": {
      "description": "The campaign no longer exists.",
      "statuses": {
        "404": "final"
      }
    },
    "campaign_not_mock_after_approve": {
      "description": "The approval did not give the campaign a mock id.",
      "statuses": {
        "409": "final"
      }
    },
    "campaign_without_brand": {
      "description": "The campaign has no brand.",
      "statuses": {
        "409": "final"
      }
    },
    "cancel_failed": {
      "description": "The cancellation failed.",
      "statuses": {
        "404": "final",
        "500": "retry_same_key"
      }
    },
    "cannot_delete": {
      "description": "The campaign cannot be deleted while it is sending.",
      "statuses": {
        "400": "final"
      }
    },
    "cannot_edit": {
      "description": "Only a draft or scheduled campaign can be edited.",
      "statuses": {
        "400": "final"
      }
    },
    "carrier_cancel_failed": {
      "description": "The carrier did not cancel the porting order.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "carrier_order_failed": {
      "description": "The carrier did not create the draft porting order.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "carrier_refused": {
      "description": "The carrier network refused the emergency address or the number's emergency calling.",
      "statuses": {
        "503": "retry_same_key"
      },
      "extra": [
        "suggested"
      ]
    },
    "carrier_submit_failed": {
      "description": "The carrier did not confirm the porting order.",
      "statuses": {
        "503": "check_before_retry"
      }
    },
    "channel_not_supported": {
      "description": "This operation does not support the requested channel.",
      "statuses": {
        "400": "final",
        "422": "final"
      }
    },
    "circuit_open": {
      "description": "The webhook's circuit breaker is open.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "circuit_opened_at",
        "circuit_state"
      ]
    },
    "compliance_blocked": {
      "description": "The message breaks a compliance rule, such as restricted content or quiet hours.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "category",
        "code",
        "matchedKeywords",
        "matchedTerms",
        "nextAllowedTime",
        "quietHoursEnd",
        "quietHoursStart",
        "reason",
        "recipient",
        "recipientLocalTime",
        "recipientTimezone",
        "suggestion"
      ]
    },
    "configuration_error": {
      "description": "The account's sending setup is incomplete, as when it has no messaging profile.",
      "statuses": {
        "500": "retry_same_key"
      },
      "sentences": [
        "Messaging not configured"
      ]
    },
    "conflict": {
      "description": "The resource conflicts with an existing one.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "existing_id"
      ]
    },
    "contact_opted_out": {
      "description": "The contact opted out.",
      "statuses": {
        "400": "final",
        "409": "final"
      }
    },
    "coverage_unavailable": {
      "description": "The carrier's coverage could not be loaded, and no earlier copy is cached.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "create_failed": {
      "description": "The resource could not be stored.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "credits_required": {
      "description": "The workspace, or its enterprise pool, has no credits.",
      "statuses": {
        "402": "final"
      },
      "sentences": [
        "Workspace must have credits before creating live keys"
      ]
    },
    "daily_call_limit": {
      "description": "The workspace has used today's outbound calling minutes.",
      "statuses": {
        "429": "final"
      }
    },
    "daily_link_limit_reached": {
      "description": "The workspace has created today's 1,000 short links. Wait for midnight UTC.",
      "statuses": {
        "429": "final"
      },
      "retryAfter": "body and header",
      "extra": [
        "limit",
        "resetsAt",
        "retryAfter"
      ]
    },
    "delete_failed": {
      "description": "The resource could not be deleted.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "delivery_failed": {
      "description": "The SMS could not be sent. Nothing is charged.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "delivery_in_progress": {
      "description": "The delivery is already queued.",
      "statuses": {
        "409": "final"
      }
    },
    "deposit_requires_payment": {
      "description": "Credits cannot be deposited into an enterprise pool without a payment: buy them in the enterprise dashboard, or ask support for an adjustment.",
      "statuses": {
        "403": "final"
      }
    },
    "destination_not_allowed": {
      "description": "The profile's `allowed_countries` leaves out the destination.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "country"
      ]
    },
    "destination_not_authorized": {
      "description": "The account's verification does not cover this destination.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "code",
        "destinationCountry"
      ]
    },
    "destination_not_supported": {
      "description": "`to` is outside the US and Canada, or a premium-rate number.",
      "statuses": {
        "400": "final"
      }
    },
    "destination_too_long": {
      "description": "The destination URL is longer than 2,048 characters.",
      "statuses": {
        "400": "final"
      }
    },
    "disabled_boolean_required": {
      "description": "`disabled` is missing or not a boolean.",
      "statuses": {
        "400": "final"
      }
    },
    "display_name_required": {
      "description": "No display name was given, and the WhatsApp business account has none to reuse.",
      "statuses": {
        "400": "final"
      }
    },
    "disposable_email": {
      "description": "The dashboard session's user signed up with a disposable email address.",
      "statuses": {
        "422": "final"
      }
    },
    "domestic_not_buyable": {
      "description": "US and Canadian numbers are set up through verification, not bought here.",
      "statuses": {
        "400": "final"
      }
    },
    "duplicate_port_request": {
      "description": "The workspace already has an open port request for this number.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "existingPortId"
      ]
    },
    "e911_not_applicable": {
      "description": "The number cannot hold an emergency address: it is not a US or Canadian number, or it is toll-free.",
      "statuses": {
        "400": "final"
      }
    },
    "e911_required": {
      "description": "The `from` number has no emergency address registered, or none being registered.",
      "statuses": {
        "428": "final"
      }
    },
    "ein_doc_upload_failed": {
      "description": "The registration document could not be stored.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "enqueue_failed": {
      "description": "The background setup could not be started. Nothing was kept, so the request can be retried.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "enterprise_inactive": {
      "description": "The enterprise account is not active.",
      "statuses": {
        "403": "final"
      }
    },
    "enterprise_required": {
      "description": "The key is not an enterprise master key.",
      "statuses": {
        "403": "final"
      },
      "sentences": [
        "Enterprise master key required"
      ]
    },
    "expired": {
      "description": "The code expired. The verification is marked expired.",
      "statuses": {
        "410": "final"
      }
    },
    "failed_to_get": {
      "description": "The number could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "failed_to_list": {
      "description": "The numbers could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "failed_to_list_assignments": {
      "description": "The assignments could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "failed_to_list_brands": {
      "description": "The brands could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "failed_to_list_campaigns": {
      "description": "The campaigns could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "failed_to_load_brand": {
      "description": "The brand could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "failed_to_load_campaign": {
      "description": "The campaign could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "failed_to_load_countries": {
      "description": "The countries could not be worked out.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "failed_to_update": {
      "description": "The number could not be updated.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "feature_disabled": {
      "description": "The feature is not enabled for the account.",
      "statuses": {
        "403": "final"
      }
    },
    "fetch_failed": {
      "description": "The resource could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "file_required": {
      "description": "No file came in the upload.",
      "statuses": {
        "400": "final"
      },
      "sentences": [
        "No file provided"
      ]
    },
    "file_too_large": {
      "description": "A file in the multipart body is larger than this endpoint takes.",
      "statuses": {
        "413": "final"
      }
    },
    "forbidden": {
      "description": "The caller's workspace role lacks the permission this needs.",
      "statuses": {
        "400": "final",
        "403": "final"
      },
      "sentences": [
        "Insufficient permissions: requires contacts:write"
      ]
    },
    "from_number_not_supported": {
      "description": "The `from` number cannot place calls: it is outside the US and Canada, or it is toll-free, which receives calls only. Also sent when `from` is missing and none of the workspace's voice-enabled numbers can place calls.",
      "statuses": {
        "400": "final"
      }
    },
    "from_number_required": {
      "description": "`from` is missing and more than one of the workspace's numbers can place calls.",
      "statuses": {
        "400": "final"
      }
    },
    "generation_failed": {
      "description": "No suggestion came back: the suggestion service is not configured, timed out, failed or answered without a template.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "group_reply_not_supported": {
      "description": "The conversation is a group, which this endpoint cannot reply to.",
      "statuses": {
        "422": "final"
      }
    },
    "hosted_cancel_unsupported": {
      "description": "This API cannot cancel a port that is not a `full_port` yet.",
      "statuses": {
        "409": "final"
      }
    },
    "hosted_submit_unsupported": {
      "description": "This API cannot submit a port that is not a `full_port` yet.",
      "statuses": {
        "409": "final"
      }
    },
    "idempotency_key_mismatch": {
      "description": "The Idempotency-Key was already used with a different body.",
      "statuses": {
        "422": "final"
      }
    },
    "ineligible_number": {
      "description": "The number is not a US local number: toll-free and non-US numbers cannot join a 10DLC campaign.",
      "statuses": {
        "422": "final"
      }
    },
    "insert_failed": {
      "description": "The upgrade could not be recorded.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "insufficient_credits": {
      "description": "The balance does not cover the request.",
      "statuses": {
        "400": "final",
        "402": "final"
      },
      "extra": [
        "available",
        "creditsNeeded",
        "currentBalance",
        "messageCount",
        "needed",
        "pricePerSms",
        "tier"
      ],
      "sentences": [
        "Insufficient credits"
      ]
    },
    "insufficient_permission": {
      "description": "The caller's role in the workspace may not do this.",
      "statuses": {
        "403": "final"
      }
    },
    "insufficient_permissions": {
      "description": "The caller may not act in this workspace, or its role lacks the permission.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "hint"
      ]
    },
    "internal_error": {
      "description": "The request failed unexpectedly.",
      "statuses": {
        "500": "retry_same_key"
      },
      "sentences": [
        "Failed to bulk provision workspaces",
        "Failed to cancel invitation",
        "Failed to create API key",
        "Failed to create invitation",
        "Failed to create opt-in page",
        "Failed to create workspace",
        "Failed to delete opt-in page",
        "Failed to delete webhook",
        "Failed to delete workspace",
        "Failed to fetch analytics",
        "Failed to fetch auto-top-up settings",
        "Failed to fetch billing breakdown",
        "Failed to fetch credit analytics",
        "Failed to fetch credits",
        "Failed to fetch delivery analytics",
        "Failed to fetch enterprise account",
        "Failed to fetch invitations",
        "Failed to fetch message analytics",
        "Failed to fetch pool credits",
        "Failed to fetch provisioning status",
        "Failed to fetch quota",
        "Failed to fetch verification status",
        "Failed to fetch webhook",
        "Failed to fetch workspace",
        "Failed to fetch workspaces",
        "Failed to inherit verification",
        "Failed to list API keys",
        "Failed to list opt-in pages",
        "Failed to list webhooks",
        "Failed to provision workspace",
        "Failed to register webhook",
        "Failed to resolve organization context",
        "Failed to resume workspace",
        "Failed to revoke API key",
        "Failed to rotate webhook secret",
        "Failed to set custom domain",
        "Failed to set webhook",
        "Failed to submit verification",
        "Failed to suspend workspace",
        "Failed to test webhook",
        "Failed to transfer credits",
        "Failed to trigger async provisioning",
        "Failed to trigger bulk provisioning",
        "Failed to update auto-top-up settings",
        "Failed to update opt-in page",
        "Failed to update quota",
        "Failed to upload file"
      ]
    },
    "international_access_required": {
      "description": "The workspace cannot send internationally, which a number outside the US needs.",
      "statuses": {
        "403": "final"
      }
    },
    "invalid_address": {
      "description": "The address could not be confirmed.",
      "statuses": {
        "400": "final",
        "422": "final"
      },
      "extra": [
        "suggested"
      ]
    },
    "invalid_api_key": {
      "description": "The API key is unknown, revoked or expired.",
      "statuses": {
        "401": "final"
      }
    },
    "invalid_auth_format": {
      "description": "The Authorization header is missing or malformed.",
      "statuses": {
        "401": "final"
      }
    },
    "invalid_body": {
      "description": "The body is not a JSON object.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_cli_token": {
      "description": "The CLI session token is unknown, revoked or expired.",
      "statuses": {
        "401": "final"
      }
    },
    "invalid_code": {
      "description": "The code is wrong. `remaining_attempts` says how many tries are left.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "remaining_attempts"
      ]
    },
    "invalid_disposition": {
      "description": "`disposition` is not `moved` or `released`.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_file": {
      "description": "The file's bytes are not a JPEG, PNG or GIF image, whatever its part declared.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_from_number": {
      "description": "`from` is not a number of this workspace that can send.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "code"
      ]
    },
    "invalid_idempotency_key": {
      "description": "The Idempotency-Key is longer than 255 characters or not printable ASCII.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_json": {
      "description": "The body is JSON that cannot be parsed, or not an object or array.",
      "statuses": {
        "400": "final"
      },
      "proposed": true
    },
    "invalid_key_format": {
      "description": "The API key is not in a valid format.",
      "statuses": {
        "401": "final"
      }
    },
    "invalid_metadata": {
      "description": "`metadata` is not an object of strings, has more than 20 keys, or a key or value is too long or a key has other characters.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_number": {
      "description": "`to` is not a valid phone number, or is the `from` number itself.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_phone": {
      "description": "A recipient is not a valid phone number.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_phone_format": {
      "description": "`to` is not a valid phone number.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_phone_number": {
      "description": "`phoneNumber` is not a phone number.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_request": {
      "description": "The request's parameters or body are invalid.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "errors",
        "totalErrors",
        "valid"
      ],
      "sentences": [
        "Amount must be greater than 0",
        "Cannot transfer to the same workspace",
        "Domain name too long",
        "Invalid EIN format. Expected: XX-XXXXXXX (e.g., 12-3456789)",
        "Invalid domain format",
        "Invalid email format",
        "Invalid instance ID",
        "Invalid period. Must be 7d, 30d, or 90d",
        "Invalid role. Must be admin, member, or viewer",
        "Provide either 'ids' (string[]) or 'listId'",
        "Provide only one of 'ids' or 'listId'",
        "amount must be a positive integer",
        "ids array capped at 10,000 per request",
        "ids must be string[]",
        "listId must be a string",
        "monthlyMessageQuota must be a positive integer or null",
        "name must be a string",
        "type must be 'test' or 'live'"
      ]
    },
    "invalid_schedule": {
      "description": "`scheduledAt` is not in the future.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_scheduled_time": {
      "description": "`scheduledAt` is not a timestamp, is less than 5 minutes away, or is more than 5 days away.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_state": {
      "description": "The resource is not in a state that allows this.",
      "statuses": {
        "400": "final",
        "409": "final"
      },
      "sentences": [
        "Workspace is already suspended",
        "Workspace is not suspended"
      ]
    },
    "invalid_status": {
      "description": "The resource's status does not allow this.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_token": {
      "description": "The token is invalid, or the session's user no longer exists.",
      "statuses": {
        "400": "final",
        "401": "final"
      },
      "extra": [
        "valid"
      ]
    },
    "invalid_upload": {
      "description": "The multipart body could not be taken: a file in a field this endpoint does not read, more files or fields than it takes, a field over its size limit, or a body that cannot be read.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_url": {
      "description": "The URL is missing, malformed or not allowed.",
      "statuses": {
        "400": "final"
      },
      "sentences": [
        "Invalid URL",
        "Invalid callbackUrl: must be HTTPS and not target internal networks",
        "Webhook URL must use HTTPS",
        "Webhook URL points to a private or reserved network"
      ]
    },
    "invalid_verification_code": {
      "description": "`code` is not 6 digits once spaces and dashes are dropped.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_voice_mode": {
      "description": "`voiceMode` is not `none`, `ring_dashboard` or `agent`.",
      "statuses": {
        "400": "final"
      }
    },
    "invalid_workspace": {
      "description": "The workspace is a personal one, which the enterprise API cannot act on.",
      "statuses": {
        "403": "final"
      }
    },
    "invitation_exists": {
      "description": "An invitation to that email is already pending.",
      "statuses": {
        "409": "final"
      },
      "sentences": [
        "Invitation already sent to this email"
      ],
      "proposed": true
    },
    "limit_exceeded": {
      "description": "The workspace already has 10 webhooks or more.",
      "statuses": {
        "400": "final"
      }
    },
    "lines_busy": {
      "description": "The workspace already has as many phone calls open as it may at once, or every line of the platform is in use.",
      "statuses": {
        "409": "wait_and_retry"
      }
    },
    "link_destination_not_allowed": {
      "description": "Short links to this destination are not allowed.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "reason"
      ]
    },
    "link_disabled_by_sendly": {
      "description": "Sendly switched this link off, so the workspace cannot switch it back on.",
      "statuses": {
        "409": "final"
      }
    },
    "link_not_found": {
      "description": "The workspace has no link with this code.",
      "statuses": {
        "404": "final"
      }
    },
    "link_screening_unavailable": {
      "description": "The destination could not be checked for threats just now, so no link was minted.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "list_lookup_failed": {
      "description": "The contact list could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "live_key_required": {
      "description": "This needs a live API key.",
      "statuses": {
        "403": "final"
      }
    },
    "max_attempts_exceeded": {
      "description": "Every attempt was used, or this wrong code used the last one. The verification is marked failed.",
      "statuses": {
        "429": "final"
      }
    },
    "messaging_activating": {
      "description": "Messaging on the ported number is still activating.",
      "statuses": {
        "409": "final"
      }
    },
    "messaging_exception": {
      "description": "Messaging on the ported number failed to activate.",
      "statuses": {
        "409": "final"
      }
    },
    "messaging_profile_required": {
      "description": "The workspace has no messaging profile yet, as before it is verified.",
      "statuses": {
        "400": "final"
      }
    },
    "messaging_profile_update_failed": {
      "description": "The workspace's sending profile could not be switched on or off.",
      "statuses": {
        "503": "retry_same_key"
      },
      "sentences": [
        "Failed to disable messaging profile. Suspension rolled back.",
        "Failed to enable messaging profile. Workspace remains suspended."
      ],
      "proposed": true
    },
    "missing_required_fields": {
      "description": "Required fields are missing.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "hint",
        "missing",
        "missingFields",
        "required"
      ],
      "sentences": [
        "Either sourceWorkspaceId (inherit) or verification (independent) is required",
        "Missing required fields: businessName, website, address, contact, useCase, useCaseSummary, sampleMessages, optInWorkflow",
        "Missing required verification fields",
        "address must include street, city, state, zip",
        "brandId, useCase, description, messageFlow, and sampleMessages are required",
        "businessName is required",
        "contact must include firstName, lastName, email, phone",
        "country and type are required",
        "domain is required",
        "email is required",
        "legalName is required",
        "name is required",
        "phoneNumber is required",
        "sourceWorkspaceId is required",
        "url is required",
        "workspace.name is required"
      ]
    },
    "missing_target": {
      "description": "`disposition` is `moved` and `targetOrgId` is missing.",
      "statuses": {
        "400": "final"
      }
    },
    "mms_unsupported_sender": {
      "description": "Media cannot be sent from a toll-free number.",
      "statuses": {
        "400": "final"
      }
    },
    "mock_mode_required": {
      "description": "The key's account is not a mock account.",
      "statuses": {
        "403": "final"
      }
    },
    "no_active_campaign": {
      "description": "The workspace has no active 10DLC campaign for the number to join.",
      "statuses": {
        "409": "final"
      }
    },
    "no_active_verification": {
      "description": "The workspace has no current verification to upgrade from.",
      "statuses": {
        "404": "final"
      }
    },
    "no_carrier_order": {
      "description": "The port request has no carrier porting order.",
      "statuses": {
        "409": "final"
      }
    },
    "no_group_sender": {
      "description": "The workspace has no number to send a group message from.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "code"
      ]
    },
    "no_pending_upgrade": {
      "description": "The workspace has no pending upgrade.",
      "statuses": {
        "404": "final"
      }
    },
    "no_recipients": {
      "description": "The campaign has no recipient who can be sent to. It is now `completed`.",
      "statuses": {
        "400": "final"
      }
    },
    "no_sending_number": {
      "description": "`to` is in the US or Canada, and the workspace's toll-free number was released with no other active number that can text there. Nothing was sent or charged.",
      "statuses": {
        "422": "final"
      }
    },
    "no_superseded_verification": {
      "description": "The workspace has no superseded entity.",
      "statuses": {
        "404": "final"
      }
    },
    "no_supported_fields": {
      "description": "The body has neither `isDefault: true` nor `pendingCancellation: false`.",
      "statuses": {
        "400": "final"
      }
    },
    "no_voice_number": {
      "description": "`from` is missing and none of the workspace's active numbers is voice-enabled.",
      "statuses": {
        "409": "final"
      }
    },
    "not_a_mock_brand": {
      "description": "The brand is not a mock brand.",
      "statuses": {
        "403": "final"
      }
    },
    "not_a_mock_campaign": {
      "description": "The campaign is not a mock campaign.",
      "statuses": {
        "403": "final"
      }
    },
    "not_awaiting_review": {
      "description": "The campaign is no longer awaiting review.",
      "statuses": {
        "409": "final"
      }
    },
    "not_cancellable": {
      "description": "The port is already final.",
      "statuses": {
        "409": "final"
      }
    },
    "not_found": {
      "description": "The resource does not exist, or the caller cannot see it.",
      "statuses": {
        "404": "final"
      },
      "sentences": [
        "API key not found",
        "Contact not found",
        "Enterprise account not found",
        "Instance not found",
        "Opt-in page not found"
      ]
    },
    "not_submittable": {
      "description": "The port is already final.",
      "statuses": {
        "409": "final"
      }
    },
    "not_us_local": {
      "description": "`countryCode` is `US` but the number is in another country that shares +1.",
      "statuses": {
        "400": "final"
      }
    },
    "not_verified": {
      "description": "The account or workspace is not verified yet.",
      "statuses": {
        "400": "final",
        "403": "final"
      },
      "extra": [
        "valid"
      ],
      "sentences": [
        "Source workspace has no active verification"
      ]
    },
    "not_workspace_member": {
      "description": "The caller is not an active member of the workspace it named.",
      "statuses": {
        "403": "final"
      },
      "sentences": [
        "Not a member of this organization"
      ],
      "proposed": true
    },
    "not_workspace_owner": {
      "description": "The key's owner does not own the workspace.",
      "statuses": {
        "403": "final"
      },
      "sentences": [
        "You must own the source workspace"
      ]
    },
    "number_already_assigned": {
      "description": "The number is assigned to another campaign. Remove it there first.",
      "statuses": {
        "409": "final"
      }
    },
    "number_in_use": {
      "description": "Another workspace still uses the number, so it cannot be released.",
      "statuses": {
        "409": "final"
      }
    },
    "number_not_eligible": {
      "description": "The number is not active yet, or is a hosted-SMS number.",
      "statuses": {
        "400": "final"
      }
    },
    "number_not_found": {
      "description": "The number is not in this workspace.",
      "statuses": {
        "404": "final"
      }
    },
    "number_not_ready": {
      "description": "The number is not set up for messaging yet.",
      "statuses": {
        "400": "final"
      }
    },
    "number_pending_release": {
      "description": "The number is scheduled for release.",
      "statuses": {
        "409": "final"
      }
    },
    "number_release_failed": {
      "description": "The carrier did not release every one of the workspace's numbers, so the workspace was kept. `failed` and `released` list the numbers.",
      "statuses": {
        "503": "retry_same_key"
      },
      "extra": [
        "failed",
        "released"
      ]
    },
    "outbound_calls_not_enabled": {
      "description": "Calls to phone numbers are not enabled for the workspace.",
      "statuses": {
        "404": "final"
      }
    },
    "payment_failed": {
      "description": "Charging the card on file failed.",
      "statuses": {
        "402": "final"
      },
      "extra": [
        "actionUrl",
        "amountCents",
        "checkoutUrl",
        "feature",
        "nextStep"
      ]
    },
    "payment_method_required": {
      "description": "The account has no card on file.",
      "statuses": {
        "402": "final"
      },
      "extra": [
        "actionUrl",
        "amountCents",
        "checkoutUrl",
        "feature",
        "nextStep"
      ]
    },
    "payment_requires_authentication": {
      "description": "The bank wants the payment confirmed. `checkoutUrl`, when present, is the secure page to confirm it on.",
      "statuses": {
        "402": "final"
      },
      "extra": [
        "actionUrl",
        "amountCents",
        "checkoutUrl",
        "feature",
        "nextStep"
      ]
    },
    "pending_never_submitted": {
      "description": "The pending upgrade never reached the carrier. Cancel it and start again.",
      "statuses": {
        "400": "final"
      }
    },
    "phone_numbers_required": {
      "description": "`phoneNumbers` is an empty array, or it is not an array and `phoneNumber` is missing or empty.",
      "statuses": {
        "400": "final"
      }
    },
    "port_record_failed": {
      "description": "The draft order was created but the request could not be recorded. Nothing was submitted.",
      "statuses": {
        "500": "check_before_retry"
      }
    },
    "port_type_unsupported": {
      "description": "`portType` is missing or is not `full_port`.",
      "statuses": {
        "400": "final"
      }
    },
    "portability_check_failed": {
      "description": "The carrier's portability check failed.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "predecessor_in_grace": {
      "description": "The key replaced another key that is still in its grace period.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "predecessorExpiresAt"
      ]
    },
    "pricing_unavailable": {
      "description": "The number could not be priced right now. Nothing was ordered: try again.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "provision_rate_limit": {
      "description": "The account made too many provisioning requests. Wait `retryAfter` seconds.",
      "statuses": {
        "429": "wait_and_retry"
      },
      "retryAfter": "body",
      "extra": [
        "retryAfter"
      ]
    },
    "provisioning_paused": {
      "description": "Provisioning is paused after repeated upstream failures, for every enterprise or for this one.",
      "statuses": {
        "503": "retry_same_key"
      },
      "extra": [
        "circuitBreaker"
      ]
    },
    "provisioning_unavailable": {
      "description": "Background provisioning is not configured, or its worker refused the server's credentials.",
      "statuses": {
        "401": "final",
        "503": "final"
      },
      "sentences": [
        "Async provisioning is not configured"
      ],
      "proposed": true
    },
    "qualify_failed": {
      "description": "The use case check failed on the carrier network.",
      "statuses": {
        "400": "final",
        "500": "retry_same_key",
        "503": "retry_same_key"
      }
    },
    "quota_exceeded": {
      "description": "The workspace has used its monthly message quota.",
      "statuses": {
        "429": "final"
      },
      "extra": [
        "batchSize",
        "quota",
        "used"
      ]
    },
    "rate_limit_exceeded": {
      "description": "The caller made too many requests. Wait `retryAfter` seconds.",
      "statuses": {
        "429": "wait_and_retry"
      },
      "retryAfter": "body and header",
      "extra": [
        "retryAfter"
      ]
    },
    "rcs_agent_ambiguous": {
      "description": "The workspace has more than one RCS agent and `agentId` is missing.",
      "statuses": {
        "400": "final"
      }
    },
    "rcs_agent_not_ready": {
      "description": "The RCS agent is not approved, suspended, or not fully set up.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "agentStatus"
      ]
    },
    "rcs_brand_not_verified": {
      "description": "The brand failed carrier verification.",
      "statuses": {
        "409": "final"
      }
    },
    "rcs_capability_check_failed": {
      "description": "Whether the recipient has RCS could not be checked.",
      "statuses": {
        "503": "retry_same_key"
      },
      "extra": [
        "suggestion"
      ]
    },
    "rcs_carrier_rejected": {
      "description": "The carrier network refused the RCS request. `message` carries its reason.",
      "statuses": {
        "422": "final"
      }
    },
    "rcs_carrier_unavailable": {
      "description": "The carrier network could not complete the RCS request.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "rcs_destination_not_supported": {
      "description": "RCS reaches US numbers only. The recipient is outside the US, and `fallbackToSms` is `false` or the message is a card.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "suggestion"
      ]
    },
    "rcs_field_locked": {
      "description": "The RCS registration is in review, so the field cannot change.",
      "statuses": {
        "409": "final"
      }
    },
    "rcs_internal_error": {
      "description": "An RCS request failed unexpectedly.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "rcs_invalid_content": {
      "description": "The RCS content is invalid.",
      "statuses": {
        "400": "final",
        "422": "final"
      },
      "extra": [
        "errors",
        "suggestion"
      ]
    },
    "rcs_launch_not_ready": {
      "description": "The agent is not approved for the carrier network or launch-rejected, or is not in testing.",
      "statuses": {
        "409": "final"
      }
    },
    "rcs_not_enabled": {
      "description": "RCS is not enabled for the account.",
      "statuses": {
        "404": "final"
      },
      "extra": [
        "suggestion"
      ]
    },
    "rcs_not_found": {
      "description": "No RCS brand or agent with this id belongs to the workspace.",
      "statuses": {
        "404": "final"
      }
    },
    "rcs_not_supported_for_recipient": {
      "description": "The recipient cannot receive RCS, and `fallbackToSms` is `false` or the message is a card.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "suggestion"
      ]
    },
    "rcs_requires_live_key": {
      "description": "RCS needs a live API key.",
      "statuses": {
        "403": "final"
      }
    },
    "rcs_send_failed": {
      "description": "The carrier network did not take the RCS message. Nothing was sent and the charge was refunded.",
      "statuses": {
        "503": "retry_same_key"
      },
      "extra": [
        "errorCode"
      ]
    },
    "rcs_send_unconfirmed": {
      "description": "The RCS network may have accepted the message. It is marked failed and refunded, but can still arrive: check before sending again.",
      "statuses": {
        "409": "check_before_retry"
      },
      "extra": [
        "errorCode"
      ]
    },
    "rcs_us_only": {
      "description": "RCS registration needs a US address.",
      "statuses": {
        "422": "final"
      }
    },
    "recipient_opted_out": {
      "description": "The recipient opted out. A short code send the carrier refused for it carries the failed message's `id` and the carrier `errorCode`.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "errorCode",
        "id"
      ]
    },
    "registration_required": {
      "description": "The contact's country needs a registered sender ID first.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "code",
        "countryCode",
        "countryName",
        "registrationUrl"
      ]
    },
    "release_failed": {
      "description": "The carrier refused to release the number or to stop hosting it, or did not release a previous number. The number is kept.",
      "statuses": {
        "400": "final",
        "503": "retry_same_key"
      }
    },
    "requirements_incomplete": {
      "description": "The secure porting form is not finished: `missing` lists what it still needs.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "missing"
      ]
    },
    "resubmit_failed": {
      "description": "The carrier refused the update. The upgrade is now `rejected`.",
      "statuses": {
        "503": "final"
      },
      "extra": [
        "details",
        "pendingVerificationId"
      ]
    },
    "resubmit_required": {
      "description": "The brand has a rejected campaign to resubmit instead.",
      "statuses": {
        "409": "final"
      }
    },
    "route_not_found": {
      "description": "No API operation has this method and path.",
      "statuses": {
        "404": "final"
      },
      "sentences": [
        "Not found"
      ],
      "proposed": true,
      "middlewareOnly": true
    },
    "sample_lint_failed": {
      "description": "One of the first five sample messages is blank, is not a string or has an unfilled placeholder, or fewer than two of them have text.",
      "statuses": {
        "422": "final"
      }
    },
    "sandbox_number_in_live_mode": {
      "description": "A live key sent to a sandbox number.",
      "statuses": {
        "400": "final"
      }
    },
    "schedule_failed": {
      "description": "The schedule could not be stored.",
      "statuses": {
        "404": "final",
        "500": "retry_same_key"
      }
    },
    "scheduling_failed": {
      "description": "The carrier refused to schedule the message. The credits are refunded, and `message` is the carrier's own error text.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "scheduling_in_progress": {
      "description": "The scheduled message is still being handed to the carrier, so it cannot be cancelled yet. Try again in a few seconds.",
      "statuses": {
        "409": "wait_and_retry"
      }
    },
    "search_failed": {
      "description": "The number search failed.",
      "statuses": {
        "500": "retry_same_key",
        "503": "retry_same_key"
      }
    },
    "self_revoke": {
      "description": "The id is the calling key's own.",
      "statuses": {
        "400": "final"
      }
    },
    "send_failed": {
      "description": "The send failed.",
      "statuses": {
        "422": "final",
        "500": "check_before_retry"
      }
    },
    "sender_not_authorized": {
      "description": "The `from` number is not authorized for this destination yet.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "code"
      ]
    },
    "server_error": {
      "description": "The request failed unexpectedly.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "short_code_ai_draft_unedited": {
      "description": "The application's only issues are wording Sendly suggested that nobody edited. `errors` lists them.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "errors"
      ]
    },
    "short_code_application_exists": {
      "description": "The workspace already has an open short code application.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "id",
        "reviewStatus",
        "status"
      ]
    },
    "short_code_cancelled": {
      "description": "The short code was cancelled and can no longer send.",
      "statuses": {
        "403": "final"
      }
    },
    "short_code_conflict": {
      "description": "Another save changed the short code application first.",
      "statuses": {
        "409": "final"
      }
    },
    "short_code_internal_error": {
      "description": "A short code request failed unexpectedly.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "short_code_invalid_application": {
      "description": "The short code application is not valid. `errors` lists the problems.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "errors"
      ]
    },
    "short_code_locked": {
      "description": "The short code application is past review, filed or live, so it cannot change.",
      "statuses": {
        "409": "final"
      }
    },
    "short_code_not_ready": {
      "description": "The short code is not live yet.",
      "statuses": {
        "403": "final"
      }
    },
    "short_code_payment_in_progress": {
      "description": "A payment of the short code setup fee is already in progress. Check back in a few minutes; it is never charged twice.",
      "statuses": {
        "409": "wait_and_retry"
      }
    },
    "short_code_payment_not_recorded": {
      "description": "The card was charged for the short code setup fee but the payment could not be recorded, so it was refunded at once.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "short_code_payment_unconfirmed": {
      "description": "The card processor could not confirm the short code setup fee. Submit again in a few minutes: a payment that went through is used, not charged again.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "short_code_refund_pending": {
      "description": "A refund of the short code setup fee is still going through. Support settles it.",
      "statuses": {
        "409": "final"
      }
    },
    "short_code_requires_live_key": {
      "description": "Short code messages need a live API key: they are never simulated.",
      "statuses": {
        "403": "final"
      }
    },
    "short_code_send_failed": {
      "description": "The carrier network did not take the short code message. It is recorded as failed and the charge was refunded.",
      "statuses": {
        "503": "retry_same_key"
      },
      "extra": [
        "errorCode",
        "id"
      ]
    },
    "short_code_send_unconfirmed": {
      "description": "The short code carrier may have accepted the message. It is marked failed and refunded, but can still arrive: check before sending again.",
      "statuses": {
        "409": "check_before_retry"
      },
      "extra": [
        "errorCode"
      ]
    },
    "short_code_suspended": {
      "description": "The short code is suspended.",
      "statuses": {
        "403": "final"
      }
    },
    "short_codes_not_enabled": {
      "description": "Short codes is not enabled for the account. A send from the workspace's own short code gets it as a 403.",
      "statuses": {
        "403": "final",
        "404": "final"
      }
    },
    "short_links_disabled": {
      "description": "Sendly has turned short links off for now.",
      "statuses": {
        "503": "wait_and_retry"
      }
    },
    "signup_not_active": {
      "description": "The signup is not waiting for a code, or was started more than 3 hours ago.",
      "statuses": {
        "409": "final"
      }
    },
    "signup_not_found": {
      "description": "No signup with this id belongs to the workspace.",
      "statuses": {
        "404": "final"
      }
    },
    "simulate_activate_failed": {
      "description": "The simulated campaign activation failed.",
      "statuses": {
        "400": "final",
        "500": "retry_same_key",
        "503": "retry_same_key"
      }
    },
    "simulate_verify_failed": {
      "description": "The simulated brand verification failed.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "sms_fallback_failed": {
      "description": "The carrier network did not take the SMS fallback. Nothing was sent and the charge was refunded.",
      "statuses": {
        "503": "retry_same_key"
      },
      "extra": [
        "errorCode"
      ]
    },
    "sms_fallback_not_supported": {
      "description": "A WhatsApp send asked for SMS fallback for a message that can't fall back: a marketing or authentication template, or media without a caption.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "reason"
      ]
    },
    "sms_fallback_unavailable": {
      "description": "The recipient cannot receive RCS, or a WhatsApp send asked for SMS fallback, and the account cannot send SMS from that number to that recipient.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "suggestion"
      ]
    },
    "sole_prop_single_campaign": {
      "description": "A sole-proprietor brand already has a live campaign.",
      "statuses": {
        "409": "final"
      }
    },
    "sole_prop_single_number": {
      "description": "A sole proprietor's campaign already has its one number.",
      "statuses": {
        "409": "final"
      }
    },
    "submission_invalid": {
      "description": "The submission has problems the carrier would refuse it for.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "blockers"
      ]
    },
    "target_not_owned": {
      "description": "`targetOrgId` names a workspace the caller does not own.",
      "statuses": {
        "403": "final"
      }
    },
    "template_already_exists": {
      "description": "The business account has a template with this name and language.",
      "statuses": {
        "409": "final"
      }
    },
    "template_authentication_no_links": {
      "description": "An authentication template may not contain links.",
      "statuses": {
        "400": "final"
      }
    },
    "template_authentication_otp_button_required": {
      "description": "An authentication template needs a one-time-code button.",
      "statuses": {
        "400": "final"
      }
    },
    "template_body_required": {
      "description": "The template has no body.",
      "statuses": {
        "400": "final"
      }
    },
    "template_body_too_long": {
      "description": "The template's body is longer than 1,024 characters.",
      "statuses": {
        "400": "final"
      }
    },
    "template_body_variable_at_edge": {
      "description": "The template's body starts or ends with a variable.",
      "statuses": {
        "400": "final"
      }
    },
    "template_button_text_too_long": {
      "description": "A button's label is longer than 25 characters.",
      "statuses": {
        "400": "final"
      }
    },
    "template_button_type_unsupported": {
      "description": "A button's type is not supported.",
      "statuses": {
        "400": "final"
      }
    },
    "template_button_url_required": {
      "description": "A URL button has no URL.",
      "statuses": {
        "400": "final"
      }
    },
    "template_category_invalid": {
      "description": "The template's category is not valid.",
      "statuses": {
        "400": "final"
      }
    },
    "template_create_failed": {
      "description": "WhatsApp could not be reached or did not answer.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "template_example_required": {
      "description": "A template with variables needs example values.",
      "statuses": {
        "400": "final"
      }
    },
    "template_footer_too_long": {
      "description": "The template's footer is longer than 60 characters.",
      "statuses": {
        "400": "final"
      }
    },
    "template_header_variable_unsupported": {
      "description": "The template's header uses a variable it may not have.",
      "statuses": {
        "400": "final"
      }
    },
    "template_language_required": {
      "description": "`language` is missing or blank.",
      "statuses": {
        "400": "final"
      }
    },
    "template_lookup_failed": {
      "description": "The contact list or the template could not be read.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "template_name_invalid": {
      "description": "The template's name is not valid.",
      "statuses": {
        "400": "final"
      }
    },
    "template_name_locked": {
      "description": "A template with this name and language was deleted less than 30 days ago. Edit a template instead.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "suggestion"
      ]
    },
    "template_name_reserved_prefix": {
      "description": "The template's name starts with a reserved prefix.",
      "statuses": {
        "400": "final"
      }
    },
    "template_not_editable": {
      "description": "The template is neither `APPROVED` nor `REJECTED`.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "templateStatus"
      ]
    },
    "template_not_found": {
      "description": "The template does not exist in this workspace.",
      "statuses": {
        "404": "final"
      }
    },
    "template_refused": {
      "description": "WhatsApp refused the template. `message` gives its reason.",
      "statuses": {
        "422": "final"
      }
    },
    "template_too_many_buttons": {
      "description": "The template has more than 3 buttons.",
      "statuses": {
        "400": "final"
      }
    },
    "template_update_failed": {
      "description": "WhatsApp could not be reached or did not answer the template change.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "test_key_restriction": {
      "description": "A test key asked for a URL that is not a test URL.",
      "statuses": {
        "400": "final"
      }
    },
    "token_already_used": {
      "description": "The token was already used.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "valid"
      ]
    },
    "toll_free_verification_required": {
      "description": "The toll-free number cannot receive texts until its toll-free verification is approved.",
      "statuses": {
        "409": "final"
      }
    },
    "too_late_to_cancel": {
      "description": "The message goes in less than a minute.",
      "statuses": {
        "400": "final"
      }
    },
    "too_many_concurrent_verifications": {
      "description": "Too many key checks are running from this address. Wait `retryAfter` seconds.",
      "statuses": {
        "429": "wait_and_retry"
      },
      "retryAfter": "body and header",
      "extra": [
        "retryAfter"
      ]
    },
    "too_many_failed_key_attempts": {
      "description": "Too many failed key checks from this address.",
      "statuses": {
        "429": "final"
      },
      "retryAfter": "body and header",
      "extra": [
        "retryAfter"
      ]
    },
    "transactional_marketing_mismatch": {
      "description": "A message marked transactional reads as marketing during quiet hours.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "code",
        "matchedKeywords",
        "reason",
        "suggestion"
      ],
      "proposed": true
    },
    "unauthorized": {
      "description": "No usable credentials, or the CLI session is invalid, expired or revoked.",
      "statuses": {
        "401": "final"
      },
      "extra": [
        "code",
        "hint"
      ]
    },
    "undeliverable_invalid": {
      "description": "The recipient's number is invalid.",
      "statuses": {
        "422": "final"
      }
    },
    "undeliverable_landline": {
      "description": "The recipient's number is a landline.",
      "statuses": {
        "422": "final"
      }
    },
    "undeliverable_non_sms": {
      "description": "The recipient's number cannot receive texts.",
      "statuses": {
        "422": "final"
      }
    },
    "undeliverable_number": {
      "description": "The recipient is flagged as unable to receive texts.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "code"
      ]
    },
    "unsupported_content_type": {
      "description": "The body declares a charset or content encoding the server cannot read.",
      "statuses": {
        "415": "final"
      },
      "proposed": true
    },
    "unsupported_destination": {
      "description": "The contact's country is not supported.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "country"
      ]
    },
    "unsupported_media_type": {
      "description": "A file in the multipart body is of a type this endpoint does not take. `message` names the types it takes.",
      "statuses": {
        "415": "final"
      }
    },
    "update_failed": {
      "description": "The change could not be stored.",
      "statuses": {
        "404": "final",
        "500": "retry_same_key"
      }
    },
    "upgrade_in_progress": {
      "description": "The workspace already has an upgrade pending.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "pendingVerificationId"
      ]
    },
    "upgrade_provisioning": {
      "description": "The business upgrade's new number is still being set up, so it cannot be cancelled yet. Try again in a minute.",
      "statuses": {
        "409": "wait_and_retry"
      }
    },
    "upload_failed": {
      "description": "The image could not be processed or stored, as when its bytes start like an image but cannot be decoded.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "user_not_found": {
      "description": "The key's user no longer exists.",
      "statuses": {
        "404": "final"
      }
    },
    "validation_error": {
      "description": "The body failed validation. `details` lists the problems.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "details"
      ]
    },
    "verification_not_found": {
      "description": "No verification with this id is the caller's.",
      "statuses": {
        "404": "final"
      }
    },
    "verification_required": {
      "description": "The workspace's business is not verified yet.",
      "statuses": {
        "403": "final"
      },
      "sentences": [
        "Workspace must be verified before creating live keys"
      ]
    },
    "voice_attach_failed": {
      "description": "Switching voice on: the carrier network or the voice network refused the change.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "voice_internal_error": {
      "description": "A voice request failed unexpectedly.",
      "statuses": {
        "500": "retry_same_key"
      }
    },
    "voice_not_enabled": {
      "description": "Voice is not enabled for the account or the number.",
      "statuses": {
        "404": "final",
        "409": "final"
      }
    },
    "voice_unavailable": {
      "description": "Voice is not available on the platform right now.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "webhook_inactive": {
      "description": "The webhook is disabled.",
      "statuses": {
        "409": "final"
      }
    },
    "webhook_not_configured": {
      "description": "No webhook URL is configured.",
      "statuses": {
        "400": "final",
        "404": "final"
      },
      "sentences": [
        "No webhook URL configured",
        "No webhook configured for this workspace",
        "No webhook configured. Set a webhook URL first."
      ],
      "proposed": true
    },
    "webhook_test_failed": {
      "description": "The test delivery failed, or no webhook with this id belongs to the workspace.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "success"
      ],
      "proposed": true
    },
    "whatsapp_activation_pending": {
      "description": "WhatsApp accepted the code, but connecting the number did not finish.",
      "statuses": {
        "503": "check_before_retry"
      }
    },
    "whatsapp_already_enabled": {
      "description": "The number is already connected.",
      "statuses": {
        "409": "final"
      }
    },
    "whatsapp_business_account_not_found": {
      "description": "The workspace has no connected WhatsApp business account with this id.",
      "statuses": {
        "404": "final"
      }
    },
    "whatsapp_calling_unavailable": {
      "description": "WhatsApp refused, or answered with calling still off: it allows calling only once the account may message at least 2,000 people a day and the display name is approved.",
      "statuses": {
        "422": "final"
      }
    },
    "whatsapp_calling_update_failed": {
      "description": "WhatsApp did not take the calling change, or could not be reached.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "whatsapp_conversational_components_fetch_failed": {
      "description": "WhatsApp did not return the conversation starters.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "whatsapp_conversational_components_update_failed": {
      "description": "WhatsApp did not take the conversation starters change.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "whatsapp_invalid_content": {
      "description": "The WhatsApp content is invalid: not exactly one of text, media or template, too long, or the wrong template variables.",
      "statuses": {
        "400": "final"
      },
      "extra": [
        "suggestion"
      ]
    },
    "whatsapp_not_enabled": {
      "description": "WhatsApp is not enabled for the account.",
      "statuses": {
        "403": "final"
      }
    },
    "whatsapp_profile_fetch_failed": {
      "description": "WhatsApp did not return the profile.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "whatsapp_profile_photo_invalid": {
      "description": "The file is not a JPEG or PNG image.",
      "statuses": {
        "400": "final"
      }
    },
    "whatsapp_profile_photo_too_large": {
      "description": "The file is larger than 5 MB.",
      "statuses": {
        "413": "final"
      }
    },
    "whatsapp_profile_update_failed": {
      "description": "WhatsApp did not take the profile change.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "whatsapp_requires_live_key": {
      "description": "WhatsApp needs a live API key.",
      "statuses": {
        "403": "final"
      }
    },
    "whatsapp_send_failed": {
      "description": "WhatsApp or the carrier network did not take the message. Nothing was sent and the charge was refunded.",
      "statuses": {
        "422": "final",
        "503": "retry_same_key"
      },
      "extra": [
        "errorCode",
        "fallback"
      ]
    },
    "whatsapp_send_unconfirmed": {
      "description": "WhatsApp may have accepted the message. It is marked failed and refunded, but can still arrive: check before sending again.",
      "statuses": {
        "409": "check_before_retry"
      },
      "extra": [
        "errorCode"
      ]
    },
    "whatsapp_sender_not_connected": {
      "description": "The sender number is not connected to WhatsApp in this workspace.",
      "statuses": {
        "403": "final",
        "404": "final"
      },
      "extra": [
        "suggestion"
      ]
    },
    "whatsapp_signup_in_progress": {
      "description": "Another WhatsApp signup for the number is in progress.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "id"
      ]
    },
    "whatsapp_signup_limit_reached": {
      "description": "Five signups failed, or 20 were cancelled, in the last 24 hours.",
      "statuses": {
        "429": "final"
      }
    },
    "whatsapp_template_not_approved": {
      "description": "The template is not approved.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "templateStatus"
      ]
    },
    "whatsapp_template_not_found": {
      "description": "No template with that name and language exists for the sender.",
      "statuses": {
        "404": "final"
      },
      "extra": [
        "suggestion"
      ]
    },
    "whatsapp_unavailable": {
      "description": "WhatsApp connections are switched off for now. Nothing was charged.",
      "statuses": {
        "503": "wait_and_retry"
      },
      "retryAfter": "body and header",
      "extra": [
        "retryAfter"
      ]
    },
    "whatsapp_verification_busy": {
      "description": "Another code for this signup is being checked.",
      "statuses": {
        "409": "wait_and_retry"
      }
    },
    "whatsapp_verification_code_invalid": {
      "description": "WhatsApp did not accept the code.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "attemptsRemaining"
      ]
    },
    "whatsapp_verification_failed": {
      "description": "Too many wrong codes. The signup is failed and the fee refunded.",
      "statuses": {
        "409": "final"
      }
    },
    "whatsapp_verification_in_progress": {
      "description": "Another signup is adding this number by code.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "id"
      ]
    },
    "whatsapp_verification_resend_failed": {
      "description": "WhatsApp would not, or could not, send another code.",
      "statuses": {
        "422": "final",
        "503": "retry_same_key"
      }
    },
    "whatsapp_verification_resend_too_soon": {
      "description": "The last code was asked for less than 30 seconds ago.",
      "statuses": {
        "429": "wait_and_retry"
      },
      "retryAfter": "body and header",
      "extra": [
        "retryAfter"
      ]
    },
    "whatsapp_verification_start_failed": {
      "description": "WhatsApp could not send the signup code. The signup is failed and the fee refunded.",
      "statuses": {
        "422": "final",
        "503": "retry_same_key"
      }
    },
    "whatsapp_verification_unavailable": {
      "description": "WhatsApp could not check the code. The attempt is not counted.",
      "statuses": {
        "503": "retry_same_key"
      }
    },
    "whatsapp_window_closed": {
      "description": "The 24-hour window is closed, so only a template can go.",
      "statuses": {
        "422": "final"
      },
      "extra": [
        "fallback",
        "id",
        "suggestion",
        "windowExpiredAt"
      ]
    },
    "workspace_access_suspended": {
      "description": "The caller's access to the workspace is suspended.",
      "statuses": {
        "403": "final"
      },
      "sentences": [
        "Your access to this organization has been suspended"
      ],
      "proposed": true
    },
    "workspace_balance_negative": {
      "description": "The workspace owes credits, so it cannot be deleted. `balance` and `reservedBalance` say how many.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "balance",
        "reservedBalance"
      ]
    },
    "workspace_has_credits": {
      "description": "The workspace holds credits, or has credits held for messages still sending, so it cannot be deleted. `balance` and `reservedBalance` say how many.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "balance",
        "reservedBalance"
      ]
    },
    "workspace_has_numbers": {
      "description": "The workspace still has phone numbers, listed in `numbers`. Release them, or delete again with `release_numbers=true`.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "numbers"
      ]
    },
    "workspace_has_unreleasable_numbers": {
      "description": "The workspace has numbers that are never released with a workspace, listed in `numbers` with a `reason`: a ported number, one needing support, or one in a port still in progress.",
      "statuses": {
        "409": "final"
      },
      "extra": [
        "numbers"
      ]
    },
    "workspace_limit_reached": {
      "description": "The enterprise account has, or would pass, as many workspaces as it may have.",
      "statuses": {
        "403": "final"
      },
      "extra": [
        "currentCount",
        "maxWorkspaces",
        "requested"
      ],
      "sentences": [
        "Workspace limit reached",
        "Would exceed workspace limit"
      ],
      "proposed": true
    },
    "workspace_name_taken": {
      "description": "A workspace with a similar name already exists.",
      "statuses": {
        "409": "final"
      },
      "sentences": [
        "A workspace with a similar name already exists"
      ],
      "proposed": true
    },
    "workspace_not_found": {
      "description": "No workspace has this id.",
      "statuses": {
        "404": "final"
      }
    },
    "workspace_required": {
      "description": "The API key belongs to no workspace.",
      "statuses": {
        "400": "final"
      }
    },
    "workspace_suspended": {
      "description": "The workspace is suspended.",
      "statuses": {
        "403": "final"
      }
    }
  },
  "x-sendly-retry-classes": {
    "wait_and_retry": "Transient, and the request did not run. Wait `retryAfter` seconds (the `Retry-After` header, else the body's `retryAfter`; with neither, back off) and retry under the same idempotency key, never waiting more than 60 seconds inside one call.",
    "retry_same_key": "The server failed, or the outcome is unknown. Retry under the same idempotency key, with backoff.",
    "final": "Waiting or retrying cannot change the answer. Change the request, or stop.",
    "check_before_retry": "The request may have taken effect. Never retry automatically: check its outcome first."
  }
}
