> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gateway.connexease.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Template

> Creates a WhatsApp message template and submits it to Meta for approval. A newly created template's status is usually `PENDING`.

## Category rules

**AUTHENTICATION** — no `header`; no `body.text` (only `addSecurityRecommendation`); no `footer.text` (only `codeExpirationMinutes`); buttons may only be `OTP`.

**UTILITY / MARKETING** — `body.text` is required; `addSecurityRecommendation` and `codeExpirationMinutes` cannot be used; `OTP` buttons are not allowed; `COPY_CODE` is allowed in `MARKETING` only.

In every category, the body and header cannot start or end with a variable, and the number of `examples` must equal the number of variables.

**TTL ranges** for `messageSendTtlSeconds`: `UTILITY` 30–43200 (30s–12h), `MARKETING` 43200–2592000 (12h–30d), `AUTHENTICATION` 30–900 or `-1`.

## Carousel rules

Sending `carousel` puts the template into carousel mode: the top level keeps only its body bubble, and every other component moves into the cards. All of these are enforced locally and fail with `422` before the request reaches Meta.

| Rule | Code |
| --- | --- |
| `category` must be `MARKETING`. | `WA_TPL_035` |
| No top-level `header` (omit it, or send `format: "NONE"`). | `WA_TPL_036` |
| No top-level `footer`. | `WA_TPL_037` |
| No top-level `buttons` — they belong to each card. | `WA_TPL_038` |
| Between 2 and 10 cards. | `WA_TPL_039` |
| Every card must use the same header format (all `IMAGE` or all `VIDEO`). | `WA_TPL_040` |
| Every card must have the same button types in the same order. | `WA_TPL_041` |
| A card header must be `IMAGE` or `VIDEO`. | `WA_TPL_042` |
| A card header must carry a media handle in `examples`. | `WA_TPL_043` |
| A card body `text` is required. | `WA_TPL_044` |
| A card body `text` is at most 160 chars. | `WA_TPL_045` |
| Card buttons may only be `QUICK_REPLY`, `URL`, or `PHONE_NUMBER`. | `WA_TPL_046` |

**Carousel is create-only.** Update Template does not accept a `carousel` field, so an existing carousel template's cards cannot be edited through this API — create a new template instead. Each card needs its own uploaded media handle, so a 5-card carousel means 5 separate Upload Media calls.

## Limited-time offer rules

Sending `limitedTimeOffer` narrows what the other components may contain. All enforced locally, `422` before reaching Meta.

| Rule | Code |
| --- | --- |
| `category` must be `MARKETING`. | `WA_TPL_048` |
| `body.text` is required and cannot be empty. | `WA_TPL_049` |
| `header.format` may only be `NONE`, `IMAGE`, or `VIDEO`. | `WA_TPL_050` |
| `footer.text` cannot be used. | `WA_TPL_051` |
| `carousel` cannot be combined with a limited-time offer. | `WA_TPL_052` |
| Buttons may only be `COPY_CODE` or `URL`. | `WA_TPL_053` |
| At most one `COPY_CODE` button. | `WA_TPL_054` |
| At most two buttons in total (instead of the usual 10). | `WA_TPL_055` |

The common pairing is one `COPY_CODE` button carrying the coupon code plus one `URL` button linking to the campaign — the maximum a limited-time offer allows.



## OpenAPI

````yaml /public-openapi.json post /wa/{app_id}/templates
openapi: 3.0.3
info:
  title: Connexease Public API
  version: 1.0.0
  description: >-
    Panel-independent API for managing WhatsApp Business operations from your
    own servers.


    Every endpoint is scoped to the organization resolved from your secret key.
    Read endpoints are uncached and proxy straight to the source.


    **On-premises installations** are served from your own domain with an extra
    `/public` segment: `https://{your_domain}/public/api/v1/...`.
    Authentication, bodies, responses, and error codes are identical.
servers:
  - url: https://public-api.gateway.connexease.com/api/v1
    description: Production
security:
  - secretKey: []
tags:
  - name: Analytics
    description: Organization-wide message volume.
  - name: Application
    description: The WhatsApp business profile linked to an application.
  - name: Template
    description: >-
      The full template lifecycle: create, list, inspect, update, delete, and
      measure.
  - name: Media
    description: >-
      Uploads that produce the single-use handle for template headers and the
      profile picture.
  - name: Developers
    description: Webhook configuration and API keys.
paths:
  /wa/{app_id}/templates:
    post:
      tags:
        - Template
      summary: Create Template
      description: >-
        Creates a WhatsApp message template and submits it to Meta for approval.
        A newly created template's status is usually `PENDING`.


        ## Category rules


        **AUTHENTICATION** — no `header`; no `body.text` (only
        `addSecurityRecommendation`); no `footer.text` (only
        `codeExpirationMinutes`); buttons may only be `OTP`.


        **UTILITY / MARKETING** — `body.text` is required;
        `addSecurityRecommendation` and `codeExpirationMinutes` cannot be used;
        `OTP` buttons are not allowed; `COPY_CODE` is allowed in `MARKETING`
        only.


        In every category, the body and header cannot start or end with a
        variable, and the number of `examples` must equal the number of
        variables.


        **TTL ranges** for `messageSendTtlSeconds`: `UTILITY` 30–43200
        (30s–12h), `MARKETING` 43200–2592000 (12h–30d), `AUTHENTICATION` 30–900
        or `-1`.


        ## Carousel rules


        Sending `carousel` puts the template into carousel mode: the top level
        keeps only its body bubble, and every other component moves into the
        cards. All of these are enforced locally and fail with `422` before the
        request reaches Meta.


        | Rule | Code |

        | --- | --- |

        | `category` must be `MARKETING`. | `WA_TPL_035` |

        | No top-level `header` (omit it, or send `format: "NONE"`). |
        `WA_TPL_036` |

        | No top-level `footer`. | `WA_TPL_037` |

        | No top-level `buttons` — they belong to each card. | `WA_TPL_038` |

        | Between 2 and 10 cards. | `WA_TPL_039` |

        | Every card must use the same header format (all `IMAGE` or all
        `VIDEO`). | `WA_TPL_040` |

        | Every card must have the same button types in the same order. |
        `WA_TPL_041` |

        | A card header must be `IMAGE` or `VIDEO`. | `WA_TPL_042` |

        | A card header must carry a media handle in `examples`. | `WA_TPL_043`
        |

        | A card body `text` is required. | `WA_TPL_044` |

        | A card body `text` is at most 160 chars. | `WA_TPL_045` |

        | Card buttons may only be `QUICK_REPLY`, `URL`, or `PHONE_NUMBER`. |
        `WA_TPL_046` |


        **Carousel is create-only.** Update Template does not accept a
        `carousel` field, so an existing carousel template's cards cannot be
        edited through this API — create a new template instead. Each card needs
        its own uploaded media handle, so a 5-card carousel means 5 separate
        Upload Media calls.


        ## Limited-time offer rules


        Sending `limitedTimeOffer` narrows what the other components may
        contain. All enforced locally, `422` before reaching Meta.


        | Rule | Code |

        | --- | --- |

        | `category` must be `MARKETING`. | `WA_TPL_048` |

        | `body.text` is required and cannot be empty. | `WA_TPL_049` |

        | `header.format` may only be `NONE`, `IMAGE`, or `VIDEO`. |
        `WA_TPL_050` |

        | `footer.text` cannot be used. | `WA_TPL_051` |

        | `carousel` cannot be combined with a limited-time offer. |
        `WA_TPL_052` |

        | Buttons may only be `COPY_CODE` or `URL`. | `WA_TPL_053` |

        | At most one `COPY_CODE` button. | `WA_TPL_054` |

        | At most two buttons in total (instead of the usual 10). | `WA_TPL_055`
        |


        The common pairing is one `COPY_CODE` button carrying the coupon code
        plus one `URL` button linking to the campaign — the maximum a
        limited-time offer allows.
      operationId: createTemplate
      parameters:
        - $ref: '#/components/parameters/AppId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - language
                - category
                - body
              properties:
                name:
                  type: string
                  maxLength: 512
                  pattern: ^[a-z][a-z0-9_]*$
                  description: >-
                    Must start with a lowercase letter and contain only
                    lowercase letters, digits, and underscores (`WA_TPL_034`).
                    Must be unique for the name + language pair, otherwise `409`
                    with `META_017`.
                language:
                  $ref: '#/components/schemas/TemplateLanguage'
                category:
                  $ref: '#/components/schemas/TemplateCategory'
                header:
                  $ref: '#/components/schemas/TemplateHeader'
                body:
                  $ref: '#/components/schemas/TemplateBody'
                footer:
                  $ref: '#/components/schemas/TemplateFooter'
                buttons:
                  type: array
                  maxItems: 10
                  items:
                    $ref: '#/components/schemas/TemplateButton'
                  description: >-
                    Not allowed together with `carousel` — carousel buttons
                    belong to each card.
                carousel:
                  type: array
                  minItems: 2
                  maxItems: 10
                  items:
                    $ref: '#/components/schemas/CarouselCard'
                  description: >-
                    Turns the template into a carousel: a body bubble followed
                    by 2–10 swipeable cards. `MARKETING` only.
                allowCategoryChange:
                  type: boolean
                  description: >-
                    When `true`, Meta may automatically re-classify the
                    template's category.
                messageSendTtlSeconds:
                  type: integer
                  description: >-
                    Message time-to-live. Valid range depends on the category —
                    see the TTL ranges above.
                limitedTimeOffer:
                  $ref: '#/components/schemas/LimitedTimeOffer'
            examples:
              utility:
                summary: UTILITY — lean
                value:
                  name: shipping_update
                  language: en
                  category: UTILITY
                  body:
                    text: Hi {{1}}, your order {{2}} is on its way.
                    examples:
                      - John
                      - '#12345'
              utilityFull:
                summary: UTILITY — header, body, footer, buttons
                value:
                  name: order_confirmation
                  language: en
                  category: UTILITY
                  header:
                    format: TEXT
                    text: 'Order #{{1}} confirmed'
                    examples:
                      - '12345'
                  body:
                    text: >-
                      Hello {{1}}, your order {{2}} has been confirmed.
                      Estimated delivery is {{3}} business days.
                    examples:
                      - John
                      - '#12345'
                      - '3'
                  footer:
                    text: Sent via Connexease
                  buttons:
                    - type: URL
                      text: Track Order
                      url: https://example.com/track/{{1}}
                      example:
                        - https://example.com/track/abc123
                    - type: PHONE_NUMBER
                      text: Call Us
                      phoneNumber: '+905551234567'
              marketingLimitedTimeOffer:
                summary: MARKETING — limited-time offer
                value:
                  name: flash_sale
                  language: en
                  category: MARKETING
                  header:
                    format: IMAGE
                    examples:
                      - 4::aW1hZ2UvcG5n:ARZ9k1sample_handle_value
                  body:
                    text: >-
                      Hi {{1}}, your flash discount is live. Use the code below
                      before it expires.
                    examples:
                      - John
                  limitedTimeOffer:
                    text: Expiring offer!
                    hasExpiration: true
                  buttons:
                    - type: COPY_CODE
                      example:
                        - FLASH40
                    - type: URL
                      text: Shop now
                      url: https://example.com/flash
              marketingCarousel:
                summary: MARKETING — carousel
                value:
                  name: summer_catalog
                  language: en
                  category: MARKETING
                  body:
                    text: Hi {{1}}, here are this week's picks.
                    examples:
                      - John
                  carousel:
                    - header:
                        format: IMAGE
                        examples:
                          - 4::aW1hZ2UvcG5n:ARZ9k1card_one_handle
                      body:
                        text: Linen shirts, now 30% off.
                      buttons:
                        - type: URL
                          text: View
                          url: https://example.com/shirts
                    - header:
                        format: IMAGE
                        examples:
                          - 4::aW1hZ2UvcG5n:ARZ9k1card_two_handle
                      body:
                        text: Summer dresses from $29.
                      buttons:
                        - type: URL
                          text: View
                          url: https://example.com/dresses
              authentication:
                summary: AUTHENTICATION — OTP
                value:
                  name: login_otp
                  language: en
                  category: AUTHENTICATION
                  body:
                    addSecurityRecommendation: true
                  footer:
                    codeExpirationMinutes: 10
                  buttons:
                    - type: OTP
                      otpType: COPY_CODE
                      text: Copy code
      responses:
        '200':
          description: The template was created and submitted for review.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/TemplateCreated'
                  isSuccess:
                    type: boolean
                    enum:
                      - true
              example:
                data:
                  sourceId: '1029384756123'
                  name: shipping_update
                  language: en
                  category: UTILITY
                  status: PENDING
                isSuccess: true
        '400':
          description: >-
            Malformed request (`REQ_001`), or Meta rejected a parameter
            (`META_021`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          description: >-
            Secret key missing or invalid (`ORGANIZATION_SECRET_010` / `011`),
            or Meta token invalid or expired (`META_018`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: Meta permission denied (`META_019`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          $ref: '#/components/responses/AppNotFound'
        '409':
          description: >-
            A template with the same `name` and `language` already exists
            (`META_017`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: >-
            Local validation before the request reaches Meta — button rules
            (`WA_TPL_001`–`005`, `015`–`020`), header rules (`WA_TPL_006`–`010`,
            `021`), body rules (`WA_TPL_011`–`014`), category rules
            (`WA_TPL_022`–`033`), the name pattern (`WA_TPL_034`), carousel
            rules (`WA_TPL_035`–`046`), and limited-time offer rules
            (`WA_TPL_048`–`055`). Meta-side validation also lands here:
            character limit (`META_022`), header / body / footer format
            (`META_023`–`025`), variable count or ratio (`META_026`), variable
            in first or last position (`META_027`), WABA migration conflict
            (`META_028`), other policy failures (`META_029`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                errors:
                  code: WA_TPL_051
                  group: VALIDATION
                  description: Limited-time offer templates do not support a footer.
                isSuccess: false
        '429':
          description: Meta rate limit (`META_020`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '502':
          description: General Meta-side creation failure (`META_003`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
components:
  parameters:
    AppId:
      name: app_id
      in: path
      required: true
      description: >-
        Application ID. Must belong to the organization resolved from your
        secret key, otherwise the request returns `404` with `APPLICATION_004`.
      schema:
        type: string
        example: app_7poyXj8GXuv76e
  schemas:
    TemplateLanguage:
      type: string
      description: >-
        Closed list — a code outside it is rejected with `422`, so this is not
        free-form BCP-47. Note that the `language` **query filter** on Get
        Templates is a plain string passed to Meta as-is and is not restricted
        to this list.
      enum:
        - af
        - sq
        - ar
        - ar_EG
        - ar_AE
        - ar_LB
        - ar_MA
        - ar_QA
        - az
        - be_BY
        - bn
        - bn_IN
        - bg
        - ca
        - zh_CN
        - zh_HK
        - zh_TW
        - hr
        - cs
        - da
        - prs_AF
        - nl
        - nl_BE
        - en
        - en_GB
        - en_US
        - en_AE
        - en_AU
        - en_CA
        - en_GH
        - en_IE
        - en_IN
        - en_JM
        - en_MY
        - en_NZ
        - en_QA
        - en_SG
        - en_UG
        - en_ZA
        - et
        - fil
        - fi
        - fr
        - fr_BE
        - fr_CA
        - fr_CH
        - fr_CI
        - fr_MA
        - ka
        - de
        - de_AT
        - de_CH
        - el
        - gu
        - ha
        - he
        - hi
        - hu
        - id
        - ga
        - it
        - ja
        - kn
        - kk
        - rw_RW
        - ko
        - ky_KG
        - lo
        - lv
        - lt
        - mk
        - ms
        - ml
        - mr
        - nb
        - ps_AF
        - fa
        - pl
        - pt_BR
        - pt_PT
        - pa
        - ro
        - ru
        - sr
        - si_LK
        - sk
        - sl
        - es
        - es_AR
        - es_CL
        - es_CO
        - es_CR
        - es_DO
        - es_EC
        - es_HN
        - es_MX
        - es_PA
        - es_PE
        - es_ES
        - es_UY
        - sw
        - sv
        - ta
        - te
        - th
        - tr
        - uk
        - ur
        - uz
        - vi
        - zu
    TemplateCategory:
      type: string
      description: >-
        Determines which components are allowed. `UTILITY` for transactional
        messages, `MARKETING` for promotional, `AUTHENTICATION` for one-time
        passcodes.
      enum:
        - UTILITY
        - MARKETING
        - AUTHENTICATION
    TemplateHeader:
      type: object
      properties:
        format:
          $ref: '#/components/schemas/HeaderFormat'
        text:
          type: string
          maxLength: 60
          description: >-
            `TEXT` headers only. Cannot start or end with a variable
            (`WA_TPL_008` / `WA_TPL_009`). Sending it on a media or `LOCATION`
            header is rejected (`WA_TPL_010` / `WA_TPL_021`).
        examples:
          type: array
          items:
            type: string
          description: >-
            Variable example for a `TEXT` header; for media headers, the media
            handle from Upload Media.
    TemplateBody:
      type: object
      properties:
        text:
          type: string
          maxLength: 1024
          description: >-
            Supports `{{1}}`, `{{2}}` variables. Cannot start or end with a
            variable (`WA_TPL_011` / `WA_TPL_012`). Required for `UTILITY` and
            `MARKETING` (`WA_TPL_027`); not allowed for `AUTHENTICATION`, where
            Meta generates it (`WA_TPL_023`).
        examples:
          type: array
          items:
            type: string
          description: >-
            Example values for the variables, in order. The count must equal the
            number of variables (`WA_TPL_014`); variables with no examples at
            all are rejected with `WA_TPL_013`.
        addSecurityRecommendation:
          type: boolean
          description: >-
            `AUTHENTICATION` only (`WA_TPL_028`). Adds Meta's security
            recommendation text.
    TemplateFooter:
      type: object
      properties:
        text:
          type: string
          maxLength: 60
          description: >-
            Not allowed in `AUTHENTICATION` (`WA_TPL_024`) or in a limited-time
            offer template (`WA_TPL_051`).
        codeExpirationMinutes:
          type: integer
          minimum: 1
          maximum: 90
          description: '`AUTHENTICATION` only (`WA_TPL_029`). How long the code stays valid.'
    TemplateButton:
      type: object
      properties:
        type:
          type: string
          enum:
            - QUICK_REPLY
            - URL
            - PHONE_NUMBER
            - COPY_CODE
            - OTP
          description: >-
            `AUTHENTICATION` accepts only `OTP`; `UTILITY` accepts neither `OTP`
            nor `COPY_CODE`; `COPY_CODE` is `MARKETING`-only.
        text:
          type: string
          minLength: 2
          maxLength: 25
          description: >-
            Required for `URL`, `PHONE_NUMBER`, and `QUICK_REPLY`
            (`WA_TPL_015`).
        url:
          type: string
          description: >-
            `URL` type only, and required for it (`WA_TPL_001`). Must start with
            `https://` and may end in a `{{1}}` variable, in which case
            `example` is required. Cannot be combined with `phoneNumber`
            (`WA_TPL_002`).
        phoneNumber:
          type: string
          description: >-
            `PHONE_NUMBER` type only, and required for it (`WA_TPL_003`). E.164
            on the way in; Meta returns it in RFC3966 form (`tel:+90-555-...`).
            Cannot be combined with `url` (`WA_TPL_004`).
        example:
          type: array
          items:
            type: string
          description: >-
            Dynamic URL example, or the coupon code for `COPY_CODE` — required
            for that type (`WA_TPL_016`).
        otpType:
          type: string
          enum:
            - COPY_CODE
            - ONE_TAP
            - ZERO_TAP
          description: >-
            Required on `OTP` buttons (`WA_TPL_017`). `COPY_CODE` has the user
            copy the code manually; `ONE_TAP` reads it with one tap; `ZERO_TAP`
            delivers it with no user action.
        autofillText:
          type: string
          maxLength: 25
          description: Optional for `ONE_TAP` / `ZERO_TAP`.
        packageName:
          type: string
          description: >-
            Android package name. Required for `ONE_TAP` / `ZERO_TAP`
            (`WA_TPL_018`).
        signatureHash:
          type: string
          description: Required for `ONE_TAP` / `ZERO_TAP` (`WA_TPL_019`).
        zeroTapTermsAccepted:
          type: boolean
          description: Must be `true` on `ZERO_TAP` buttons (`WA_TPL_020`).
      required:
        - type
    CarouselCard:
      type: object
      description: >-
        One carousel card. Every card must be structurally identical to the
        others: same header format, same button types in the same order.
      properties:
        header:
          $ref: '#/components/schemas/TemplateHeader'
        body:
          $ref: '#/components/schemas/TemplateBody'
        buttons:
          type: array
          minItems: 1
          maxItems: 2
          items:
            $ref: '#/components/schemas/TemplateButton'
          description: >-
            Only `QUICK_REPLY`, `URL`, and `PHONE_NUMBER` are allowed
            (`WA_TPL_046`).
      required:
        - header
        - body
        - buttons
    LimitedTimeOffer:
      type: object
      properties:
        text:
          type: string
          minLength: 1
          maxLength: 16
          description: Offer text on the banner, e.g. `Expiring offer!`.
        hasExpiration:
          type: boolean
          default: false
          description: >-
            When `true`, WhatsApp renders a countdown. This only controls
            whether the countdown is shown — the expiration timestamp itself is
            supplied per message at send time, so one approved template can
            serve different deadlines.
      required:
        - text
    TemplateCreated:
      type: object
      description: >-
        Lean creation response. It does not carry `components`, `qualityScore`,
        `rejectedReason`, `parameterFormat`, or the DB id — fetch those with Get
        Template Detail or Get Templates.
      properties:
        sourceId:
          type: string
          description: The template's Meta ID.
        name:
          type: string
        language:
          type: string
        category:
          $ref: '#/components/schemas/TemplateCategory'
        status:
          $ref: '#/components/schemas/TemplateStatus'
    ErrorEnvelope:
      type: object
      description: >-
        Every failure shares this shape. `description` already has any `params`
        interpolated into it.
      properties:
        isSuccess:
          type: boolean
          enum:
            - false
        errors:
          type: object
          properties:
            code:
              type: string
              description: >-
                `VAL_*`, `WA_*`, `META_*`, `APPLICATION_*`,
                `ORGANIZATION_SECRET_*`, `REQ_001`, or `SYS_001`.
              example: META_075
            group:
              type: string
              enum:
                - VALIDATION
                - NOT_FOUND
                - CONFLICT
                - AUTHENTICATION
                - NOT_ALLOWED
                - LIMIT_EXCEEDED
                - SERVICE_UNAVAILABLE
                - SYSTEM
            description:
              type: string
              example: Template with 0000000000 not found in Meta.
            params:
              type: object
              additionalProperties: true
              description: >-
                Raw values interpolated into `description`. Present only on
                parametric messages.
            fields:
              type: object
              description: >-
                Field-level validation errors only. Field name (dot-joined for
                nested fields, list indices omitted) to its own `code` /
                `description` / `params`.
              additionalProperties:
                type: object
                properties:
                  code:
                    type: string
                  description:
                    type: string
                  params:
                    type: object
                    additionalProperties: true
          required:
            - code
            - group
            - description
      required:
        - isSuccess
        - errors
    HeaderFormat:
      type: string
      description: >-
        `NONE` is the default when `header` is omitted. `AUTHENTICATION` allows
        no header at all; a carousel card header must be `IMAGE` or `VIDEO`; a
        limited-time offer header is limited to `NONE` / `IMAGE` / `VIDEO`.
      enum:
        - NONE
        - TEXT
        - IMAGE
        - VIDEO
        - DOCUMENT
        - LOCATION
    TemplateStatus:
      type: string
      description: >-
        Review and lifecycle status. `UNKNOWN` means Meta reported a status this
        API does not recognise.
      enum:
        - APPROVED
        - PENDING
        - REJECTED
        - PAUSED
        - DISABLED
        - IN_APPEAL
        - PENDING_DELETION
        - DELETED
        - LIMIT_EXCEEDED
        - UNKNOWN
  responses:
    AppNotFound:
      description: '`app_id` does not belong to the organization (`APPLICATION_004`).'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  securitySchemes:
    secretKey:
      type: http
      scheme: bearer
      description: >-
        Secret key in `Bearer sk_...` format. Server-to-server only — never
        embed it in a browser or mobile client. The organization is resolved
        from the key, so `organization_id` is never passed explicitly.

````