> ## Documentation Index
> Fetch the complete documentation index at: https://developers.tassyir.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Resume a paused offer

> Starts a paused offer again; the plan's `active_offers` cap applies. An ended offer is not resumed: move its end date instead. Resuming an offer that is not paused changes nothing. An app changes, and reads the codes and redemptions of, only the offers its own installation created (`ownerInstallationId` is set from the token when it creates one). A merchant's offer, or another app's, is 403 `OFFER_NOT_OWNED`; an offer the token cannot see (another business, a store outside the installation's stores) is 404.

Needs the `write_offers` scope (permission `offers:update`).



## OpenAPI

````yaml /openapi/openapi.2026-10.json post /apps/2026-10/offers/{id}/resume
openapi: 3.1.0
info:
  title: Tassyir Admin API
  version: 2026-10
  summary: >-
    The API installed apps call to read and change a Tassyir business, and the
    webhooks they receive.
  description: >-
    Version `2026-10` of the API installed Tassyir apps call. The routes live
    under `/apps/2026-10/`; the token endpoint and the key documents under
    `/apps/`. Guides, and a page for every error code:
    https://developers.tassyir.io.


    **Authentication.** `Authorization: Bearer tsy_at_…` from `POST
    /apps/oauth/token`. An app acts as a team member of the business: it reads
    and writes only what its granted scopes allow, only in the stores the
    merchant gave it, under the merchant's plan. An app on Tassyir Hosting holds
    no token: it calls these routes through `ctx.props.TASSYIR.fetch`, which
    signs each call as its installation (the same scopes, stores and plan;
    Idempotency-Key passes through), and a call that cannot be accepted is 401
    `HOSTED_CALL_REFUSED`.


    **Conventions.** JSON fields are camelCase; ids are strings; times are ISO
    8601 UTC; money is a decimal string (`"2500.00"`) with a `currency` field,
    never a number. A list answers `{ data, nextCursor }`, newest first,
    keyset-paged: `limit` 1 to 100 (default 50), `cursor` = the previous
    `nextCursor`. A single resource answers `{ data }`. `fields` trims a
    resource to the named top-level fields. Fields without
    `read_customer_contact` (buyer name, phones, address, notes) are omitted,
    not nulled. Every answer is `Cache-Control: no-store`.


    **Writes.** Send an `Idempotency-Key` to make a write safe to retry (24
    hours per installation).


    **Errors.** `application/problem+json` with a stable `code`, a `fix`
    sentence, the `docs` page of the code and a `requestId`. Each operation
    lists every code it can answer; `x-tassyir-errors` lists every code a
    problem can carry, with its title, statuses and `fix`. HTTP 460
    `STORE_SCOPE_FORBIDDEN` means a store outside the installation's stores.


    **Rate limits.** A leaky bucket per installation, by default 40 requests
    refilled at 4 a second: every answer carries `RateLimit-Limit`,
    `RateLimit-Remaining` and `RateLimit-Reset`; a refusal is 429 `RATE_LIMITED`
    with `Retry-After`. All the apps of one business also share a ceiling, by
    default 20 requests a second: 429 `BUSINESS_RATE_LIMITED` with
    `Retry-After`. An API process that is already running its maximum of app
    requests answers 503 `API_BUSY` with `Retry-After`, having done nothing.


    **Webhooks.** Signed Standard Webhooks deliveries (`v1a`, Ed25519), one per
    topic below; verify them with `GET /apps/webhook-keys`.
servers:
  - url: https://api.tassyir.io
security:
  - appAccessToken: []
tags:
  - name: Authentication
    description: Tokens and the public keys apps verify with.
  - name: Business
    description: The business the app is installed on.
  - name: Orders
    description: Orders, their comments and the cancel reasons.
  - name: Products
    description: Products and their variants.
  - name: Collections
    description: Collections and their members.
  - name: Inventory
    description: Stock levels.
  - name: Customers
    description: The buyers behind the orders.
  - name: Offers
    description: >-
      The merchant's per-store pricing offers (read them with read_offers), and
      the offers an app creates and manages itself, with their codes and
      redemptions (write_offers).
  - name: Stores
    description: The installation's stores.
  - name: Delivery
    description: Delivery agents and fee groups (never credentials).
  - name: Data
    description: >-
      Typed values the app keeps on the business, its stores, products, orders
      and customers, under keys its manifest declares.
  - name: Images
    description: >-
      Images re-hosted on the Tassyir CDN, for the product and collection
      writes.
  - name: Bulk exports
    description: >-
      A whole list (orders, products, customers) as one JSON Lines file, instead
      of paging through it.
  - name: Webhooks
    description: What Tassyir POSTs to the app.
paths:
  /apps/2026-10/offers/{id}/resume:
    post:
      tags:
        - Offers
      summary: Resume a paused offer
      description: >-
        Starts a paused offer again; the plan's `active_offers` cap applies. An
        ended offer is not resumed: move its end date instead. Resuming an offer
        that is not paused changes nothing. An app changes, and reads the codes
        and redemptions of, only the offers its own installation created
        (`ownerInstallationId` is set from the token when it creates one). A
        merchant's offer, or another app's, is 403 `OFFER_NOT_OWNED`; an offer
        the token cannot see (another business, a store outside the
        installation's stores) is 404.


        Needs the `write_offers` scope (permission `offers:update`).
      operationId: resumeOffer
      parameters:
        - name: id
          in: path
          required: true
          description: >-
            A resource id. One this installation cannot read, or a malformed
            one, is 404 `NOT_FOUND`.
          schema:
            type: string
            minLength: 1
        - name: fields
          in: query
          required: false
          schema:
            maxLength: 1000
            type: string
          description: >-
            Return only these top-level fields, separated by commas; the id is
            always kept. The response schema describes the whole resource. An
            unknown name is 400 `INVALID_FIELDS`. Fields: `id`, `storeId`,
            `kind`, `method`, `title`, `label`, `status`, `currency`,
            `quantity`, `freeDelivery`, `productDiscount`, `orderDiscount`,
            `bxgy`, `addon`, `appRule`, `combinesWith`, `eligibility`,
            `targets`, `codeCount`, `totalUsageLimit`, `perBuyerLimit`,
            `startsAt`, `endsAt`, `publishedAt`, `pausedAt`, `archivedAt`,
            `appOwned`, `createdAt`, `updatedAt`.
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OfferActionInput'
      responses:
        '200':
          description: The offer as it is now.
          headers:
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            Cache-Control:
              $ref: '#/components/headers/Cache-Control-No-Store'
            Idempotent-Replayed:
              $ref: '#/components/headers/Idempotent-Replayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OfferResponse'
        '400':
          description: >-
            Bad request: `BAD_REQUEST`, `IDEMPOTENCY_KEY_INVALID`,
            `INVALID_FIELDS`, `VALIDATION_FAILED`.
          headers:
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Problem'
                  - properties:
                      status:
                        const: 400
                      code:
                        enum:
                          - BAD_REQUEST
                          - IDEMPOTENCY_KEY_INVALID
                          - INVALID_FIELDS
                          - VALIDATION_FAILED
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            Not allowed: `OFFER_NOT_OWNED`, `PERMISSION_DENIED`,
            `PLAN_LIMIT_REACHED`.
          headers:
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Problem'
                  - properties:
                      status:
                        const: 403
                      code:
                        enum:
                          - OFFER_NOT_OWNED
                          - PERMISSION_DENIED
                          - PLAN_LIMIT_REACHED
        '404':
          description: 'Not found: `NOT_FOUND`, `OFFER_NOT_FOUND`.'
          headers:
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Problem'
                  - properties:
                      status:
                        const: 404
                      code:
                        enum:
                          - NOT_FOUND
                          - OFFER_NOT_FOUND
        '409':
          description: >-
            Conflict: `IDEMPOTENCY_KEY_IN_USE`, `OFFER_ARCHIVED`, `OFFER_ENDED`,
            `OFFER_NOT_PUBLISHED`, `OFFER_VERSION_CONFLICT`.
          headers:
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Problem'
                  - properties:
                      status:
                        const: 409
                      code:
                        enum:
                          - IDEMPOTENCY_KEY_IN_USE
                          - OFFER_ARCHIVED
                          - OFFER_ENDED
                          - OFFER_NOT_PUBLISHED
                          - OFFER_VERSION_CONFLICT
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '415':
          $ref: '#/components/responses/UnsupportedMediaType'
        '422':
          description: 'Unprocessable: `IDEMPOTENCY_KEY_REUSED`.'
          headers:
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/problem+json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Problem'
                  - properties:
                      status:
                        const: 422
                      code:
                        enum:
                          - IDEMPOTENCY_KEY_REUSED
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/UnavailableForWrite'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        Makes a write safe to retry: the same key with the same method, path,
        query and body within 24 hours answers the stored result
        (`Idempotent-Replayed: true`) without running the write again. Only a
        successful answer is stored, so a retry after a failure runs. A key
        reused for a different request is 422 `IDEMPOTENCY_KEY_REUSED`; one
        whose first request still runs is 409 `IDEMPOTENCY_KEY_IN_USE`.
      schema:
        type: string
        minLength: 1
        maxLength: 255
        pattern: ^[\x21-\x7E]+$
      example: 3f2a1c9e-8a4b-4f5e-9d61-2c7b0e4a91d3
  schemas:
    OfferActionInput:
      type: object
      properties:
        expectedVersion:
          anyOf:
            - minimum: 1
              type: integer
            - type: 'null'
      additionalProperties: false
    OfferResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Offer'
      required:
        - data
      additionalProperties: false
    Problem:
      type: object
      description: >-
        An Admin API error (RFC 9457 problem details), served as
        `application/problem+json`. Act on `code`, never on `detail`. Other
        members name the subject of the refusal (`permission`, `storeId`,
        `feature`, `limit`, `errors`, …).
      properties:
        type:
          type: string
          format: uri
          description: >-
            `https://developers.tassyir.io/errors/<code in kebab case>`:
            identifies the code, and is the code's page.
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
          description: >-
            For a person. A 5xx never carries an internal message: `requestId`
            names it.
        code:
          type: string
          pattern: ^[A-Z][A-Z0-9_]{1,63}$
          description: 'Stable: what the app acts on.'
        fix:
          type: string
          description: One sentence an AI agent can act on.
        docs:
          type: string
          format: uri
          description: >-
            The page that explains the code and what to do: the same URL as
            `type`.
        requestId:
          type: string
          description: Also in the `X-Request-Id` header. Quote it to Tassyir.
        errors:
          type: array
          items:
            type: string
          description: 'With `VALIDATION_FAILED`: one entry per invalid parameter.'
      required:
        - type
        - title
        - status
        - detail
        - code
        - docs
    Offer:
      type: object
      properties:
        id:
          type: string
          minLength: 1
          maxLength: 64
          description: A resource id (a snowflake id, as a string).
        storeId:
          type: string
          minLength: 1
          maxLength: 64
          description: The store the offer belongs to.
        kind:
          type: string
          description: >-
            quantity, free_delivery, product_discount, order_discount, bxgy,
            addon or app. Ignore a kind you do not know.
        method:
          type: string
          description: automatic or code.
        title:
          type: string
          description: The merchant's name for the offer.
        label:
          anyOf:
            - type: object
              properties:
                ar:
                  anyOf:
                    - type: string
                    - type: 'null'
                fr:
                  anyOf:
                    - type: string
                    - type: 'null'
                en:
                  anyOf:
                    - type: string
                    - type: 'null'
              required:
                - ar
                - fr
                - en
              additionalProperties: false
            - type: 'null'
          description: What the buyer reads, per language.
        status:
          type: string
          description: >-
            draft, scheduled, active, paused or ended (derived from the dates
            and the lifecycle timestamps; an archived offer is ended).
        currency:
          type: string
          pattern: ^[A-Z]{3}$
          description: ISO 4217 currency code of every amount in this resource.
        quantity:
          anyOf:
            - type: object
              properties:
                priceMode:
                  type: string
                  description: total, percent or amount_each.
                tiers:
                  type: array
                  items:
                    type: object
                    properties:
                      pieces:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                        description: Pieces the tier is for.
                      label:
                        type: object
                        properties:
                          ar:
                            anyOf:
                              - type: string
                              - type: 'null'
                          fr:
                            anyOf:
                              - type: string
                              - type: 'null'
                          en:
                            anyOf:
                              - type: string
                              - type: 'null'
                        required:
                          - ar
                          - fr
                          - en
                        additionalProperties: false
                        description: What the buyer reads on the tier card.
                      total:
                        anyOf:
                          - type: string
                            pattern: ^-?\d+\.\d{2}$
                            description: >-
                              A decimal amount with two decimals, as a string
                              ("2500.00").
                          - type: 'null'
                        description: 'priceMode total: the whole price of the tier.'
                      percentOff:
                        anyOf:
                          - type: number
                          - type: 'null'
                        description: 'priceMode percent: 1 to 100, off each piece.'
                      amountOffEach:
                        anyOf:
                          - type: string
                            pattern: ^-?\d+\.\d{2}$
                            description: >-
                              A decimal amount with two decimals, as a string
                              ("2500.00").
                          - type: 'null'
                        description: 'priceMode amount_each: DZD off each piece.'
                      preselected:
                        type: boolean
                      freeDelivery:
                        type: boolean
                    required:
                      - pieces
                      - label
                      - total
                      - percentOff
                      - amountOffEach
                      - preselected
                      - freeDelivery
                    additionalProperties: false
              required:
                - priceMode
                - tiers
              additionalProperties: false
            - type: 'null'
          description: kind quantity only.
        freeDelivery:
          anyOf:
            - type: object
              properties:
                thresholdKind:
                  anyOf:
                    - type: string
                    - type: 'null'
                  description: pieces or amount; null while the offer has none (a draft).
                thresholdPieces:
                  anyOf:
                    - type: integer
                      minimum: -9007199254740991
                      maximum: 9007199254740991
                    - type: 'null'
                thresholdAmount:
                  anyOf:
                    - type: string
                      pattern: ^-?\d+\.\d{2}$
                      description: >-
                        A decimal amount with two decimals, as a string
                        ("2500.00").
                    - type: 'null'
                delivery:
                  type: string
                  description: home, desk or both.
                wilayas:
                  type: array
                  items:
                    type: string
                  description: Two-digit wilaya codes; empty = every wilaya.
              required:
                - thresholdKind
                - thresholdPieces
                - thresholdAmount
                - delivery
                - wilayas
              additionalProperties: false
            - type: 'null'
          description: kind free_delivery only.
        productDiscount:
          anyOf:
            - type: object
              properties:
                valueType:
                  type: string
                  description: percent or fixed.
                percent:
                  anyOf:
                    - type: number
                    - type: 'null'
                  description: 'valueType percent: 1 to 100.'
                amount:
                  anyOf:
                    - type: string
                      pattern: ^-?\d+\.\d{2}$
                      description: >-
                        A decimal amount with two decimals, as a string
                        ("2500.00").
                    - type: 'null'
                  description: 'valueType fixed: DZD off each unit.'
                maxAmount:
                  anyOf:
                    - type: string
                      pattern: ^-?\d+\.\d{2}$
                      description: >-
                        A decimal amount with two decimals, as a string
                        ("2500.00").
                    - type: 'null'
                  description: Cap on a percentage saving per unit, DZD.
                showCountdown:
                  type: boolean
                  description: A countdown to the offer's end date is shown.
              required:
                - valueType
                - percent
                - amount
                - maxAmount
                - showCountdown
              additionalProperties: false
            - type: 'null'
          description: kind product_discount only.
        orderDiscount:
          anyOf:
            - type: object
              properties:
                valueType:
                  type: string
                  description: percent or fixed.
                percent:
                  anyOf:
                    - type: number
                    - type: 'null'
                  description: 'valueType percent: 1 to 100.'
                amount:
                  anyOf:
                    - type: string
                      pattern: ^-?\d+\.\d{2}$
                      description: >-
                        A decimal amount with two decimals, as a string
                        ("2500.00").
                    - type: 'null'
                  description: 'valueType fixed: DZD off the order.'
                maxAmount:
                  anyOf:
                    - type: string
                      pattern: ^-?\d+\.\d{2}$
                      description: >-
                        A decimal amount with two decimals, as a string
                        ("2500.00").
                    - type: 'null'
                  description: 'valueType percent: the most the order''s saving may reach.'
                minimumKind:
                  anyOf:
                    - type: string
                    - type: 'null'
                  description: pieces or amount; null = every order.
                minimumPieces:
                  anyOf:
                    - type: integer
                      minimum: -9007199254740991
                      maximum: 9007199254740991
                    - type: 'null'
                minimumAmount:
                  anyOf:
                    - type: string
                      pattern: ^-?\d+\.\d{2}$
                      description: >-
                        A decimal amount with two decimals, as a string
                        ("2500.00").
                    - type: 'null'
              required:
                - valueType
                - percent
                - amount
                - maxAmount
                - minimumKind
                - minimumPieces
                - minimumAmount
              additionalProperties: false
            - type: 'null'
          description: kind order_discount only.
        bxgy:
          anyOf:
            - type: object
              properties:
                buyPieces:
                  type: integer
                  minimum: -9007199254740991
                  maximum: 9007199254740991
                  description: Paid pieces of the buy targets per set.
                getPieces:
                  type: integer
                  minimum: -9007199254740991
                  maximum: 9007199254740991
                  description: Discounted pieces per set.
                getDiscountType:
                  type: string
                  description: >-
                    percent (100 = free) or fixed_price (the gift price per
                    piece).
                getPercent:
                  anyOf:
                    - type: number
                    - type: 'null'
                getPrice:
                  anyOf:
                    - type: string
                      pattern: ^-?\d+\.\d{2}$
                      description: >-
                        A decimal amount with two decimals, as a string
                        ("2500.00").
                    - type: 'null'
                maxPerOrder:
                  anyOf:
                    - type: integer
                      minimum: -9007199254740991
                      maximum: 9007199254740991
                    - type: 'null'
                  description: Sets per order; null = as many as the cart holds.
              required:
                - buyPieces
                - getPieces
                - getDiscountType
                - getPercent
                - getPrice
                - maxPerOrder
              additionalProperties: false
            - type: 'null'
          description: kind bxgy only (buy X get Y).
        addon:
          anyOf:
            - type: object
              properties:
                priceType:
                  anyOf:
                    - type: string
                    - type: 'null'
                  description: >-
                    fixed_price, percent or amount_off; null while a draft has
                    none.
                price:
                  anyOf:
                    - type: string
                      pattern: ^-?\d+\.\d{2}$
                      description: >-
                        A decimal amount with two decimals, as a string
                        ("2500.00").
                    - type: 'null'
                  description: priceType fixed_price.
                percent:
                  anyOf:
                    - type: number
                    - type: 'null'
                  description: priceType percent.
                amountOff:
                  anyOf:
                    - type: string
                      pattern: ^-?\d+\.\d{2}$
                      description: >-
                        A decimal amount with two decimals, as a string
                        ("2500.00").
                    - type: 'null'
                  description: priceType amount_off.
                maxQuantity:
                  type: integer
                  minimum: -9007199254740991
                  maximum: 9007199254740991
                beforeSubmit:
                  type: boolean
                  description: Offered in the order form.
                afterSubmit:
                  type: boolean
                  description: Offered on the thank-you page.
              required:
                - priceType
                - price
                - percent
                - amountOff
                - maxQuantity
                - beforeSubmit
                - afterSubmit
              additionalProperties: false
            - type: 'null'
          description: kind addon only.
        appRule:
          anyOf:
            - type: object
              properties:
                typeHandle:
                  type: string
                  description: The owning app's [[offers.types]] handle.
                rule:
                  description: >-
                    The declarative rule as the app wrote it: { class, when,
                    then } (see the offers guide).
              required:
                - typeHandle
                - rule
              additionalProperties: false
            - type: 'null'
          description: 'kind app only: an app-owned offer type and its rule.'
        combinesWith:
          type: object
          properties:
            product:
              type: boolean
            order:
              type: boolean
            delivery:
              type: boolean
          required:
            - product
            - order
            - delivery
          additionalProperties: false
          description: Which classes of offer this one stacks with.
        eligibility:
          type: object
          properties:
            audience:
              type: string
              description: everyone, first_order or returning.
            channels:
              type: array
              items:
                type: string
              description: store, landing, shopify, dashboard, apps; empty = all.
            wilayas:
              type: array
              items:
                type: string
              description: Empty = every wilaya.
            deliveryMethods:
              type: array
              items:
                type: string
              description: home, desk; empty = both.
          required:
            - audience
            - channels
            - wilayas
            - deliveryMethods
          additionalProperties: false
        targets:
          type: array
          items:
            type: object
            properties:
              role:
                type: string
                description: buy (what the offer applies to), get or addon.
              type:
                type: string
                description: all, product, variant or collection.
              id:
                anyOf:
                  - type: string
                    minLength: 1
                    maxLength: 64
                    description: A resource id (a snowflake id, as a string).
                  - type: 'null'
                description: Null when type is all.
            required:
              - role
              - type
              - id
            additionalProperties: false
          description: What the offer applies to (empty for a free-delivery offer).
        codeCount:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: Codes buyers can still use (0 for an automatic offer).
        totalUsageLimit:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
          description: Total uses; null = unlimited.
        perBuyerLimit:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
          description: Uses per buyer (phone number); null = unlimited.
        startsAt:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          description: ISO 8601 date-time, UTC.
        endsAt:
          anyOf:
            - type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              description: ISO 8601 date-time, UTC.
            - type: 'null'
        publishedAt:
          anyOf:
            - type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              description: ISO 8601 date-time, UTC.
            - type: 'null'
          description: Null while the offer is a draft.
        pausedAt:
          anyOf:
            - type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              description: ISO 8601 date-time, UTC.
            - type: 'null'
        archivedAt:
          anyOf:
            - type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              description: ISO 8601 date-time, UTC.
            - type: 'null'
        appOwned:
          type: boolean
          description: The offer belongs to an installed app (phase 2 kinds).
        createdAt:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          description: ISO 8601 date-time, UTC.
        updatedAt:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          description: ISO 8601 date-time, UTC.
      required:
        - id
        - storeId
        - kind
        - method
        - title
        - label
        - status
        - currency
        - quantity
        - freeDelivery
        - productDiscount
        - orderDiscount
        - bxgy
        - addon
        - appRule
        - combinesWith
        - eligibility
        - targets
        - codeCount
        - totalUsageLimit
        - perBuyerLimit
        - startsAt
        - endsAt
        - publishedAt
        - pausedAt
        - archivedAt
        - appOwned
        - createdAt
        - updatedAt
      additionalProperties: false
      description: An offer (API 2026-10).
  headers:
    RateLimit-Limit:
      description: >-
        The installation's request bucket (default 40); on a 429
        `BUSINESS_RATE_LIMITED`, the business's ceiling (default 20 a second).
        Absent when a request is refused before the rate limits run (an
        unparsable body, a 503 `API_BUSY`).
      schema:
        minimum: 1
        type: integer
    RateLimit-Remaining:
      description: Requests still accepted right now.
      schema:
        type: integer
        minimum: 0
    RateLimit-Reset:
      description: >-
        Seconds until the bucket is empty again (it drains at 4 requests a
        second by default).
      schema:
        type: integer
        minimum: 0
    X-Request-Id:
      description: The request's id, also in an error's `requestId`.
      schema:
        type: string
    Cache-Control-No-Store:
      description: '`no-store`: never cache an answer.'
      schema:
        type: string
        const: no-store
    Idempotent-Replayed:
      description: >-
        Present on the stored answer of a write repeated with the same
        `Idempotency-Key`: the write did not run again.
      schema:
        type: string
        const: 'true'
    Retry-After:
      description: Seconds to wait before retrying.
      schema:
        type: integer
        minimum: 0
  responses:
    Unauthorized:
      description: >-
        No usable credential: `APP_TOKEN_INVALID`, `APP_TOKEN_REQUIRED`,
        `HOSTED_CALL_REFUSED`.
      headers:
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        WWW-Authenticate:
          description: >-
            The challenge: `Bearer` (RFC 6750) for an access token,
            `Tassyir-Hosted` for a hosted app's call through
            `ctx.props.TASSYIR`.
          schema:
            type: string
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 401
                  code:
                    enum:
                      - APP_TOKEN_INVALID
                      - APP_TOKEN_REQUIRED
                      - HOSTED_CALL_REFUSED
    PayloadTooLarge:
      description: 'Body too large: `PAYLOAD_TOO_LARGE`.'
      headers:
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 413
                  code:
                    enum:
                      - PAYLOAD_TOO_LARGE
    UnsupportedMediaType:
      description: 'Unsupported body: `UNSUPPORTED_MEDIA_TYPE`.'
      headers:
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 415
                  code:
                    enum:
                      - UNSUPPORTED_MEDIA_TYPE
    RateLimited:
      description: 'Rate limited: `BUSINESS_RATE_LIMITED`, `RATE_LIMITED`.'
      headers:
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        Retry-After:
          $ref: '#/components/headers/Retry-After'
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 429
                  code:
                    enum:
                      - BUSINESS_RATE_LIMITED
                      - RATE_LIMITED
    InternalError:
      description: 'Internal error: `INTERNAL_ERROR`.'
      headers:
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 500
                  code:
                    enum:
                      - INTERNAL_ERROR
    UnavailableForWrite:
      description: >-
        Unavailable: `API_BUSY`, `IDEMPOTENCY_UNAVAILABLE`,
        `SERVICE_UNAVAILABLE`.
      headers:
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        Retry-After:
          $ref: '#/components/headers/Retry-After'
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 503
                  code:
                    enum:
                      - API_BUSY
                      - IDEMPOTENCY_UNAVAILABLE
                      - SERVICE_UNAVAILABLE
  securitySchemes:
    appAccessToken:
      type: http
      scheme: bearer
      bearerFormat: tsy_at_<43 base62>
      description: >-
        An app access token from `POST /apps/oauth/token`, valid 1 hour. An
        offline token acts as the app; an online token acts as the app on behalf
        of one dashboard user (the intersection of both permission sets).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.