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

# Take a product off sale

> Move the product to `ARCHIVED`. It stops being sellable at checkout;
subscriptions already running on it keep renewing.

Nothing is ever deleted · past payments reference the row, and a receipt
from last year still has to render. Empty body.




## OpenAPI

````yaml /v3-beta/api-reference/openapi.yaml post /v3/products/{id}/archive
openapi: 3.1.0
info:
  title: Suby.fi Merchant API
  version: 3.0.0-beta
  description: >
    The **v3** public merchant API for Suby.fi. RESTful (plural,
    resource-oriented

    endpoints under the `/v3` prefix). Authenticate every request

    with your secret API key in the `X-Suby-Api-Key` header.


    - `sk_live_…` keys operate in **production** (real funds).

    - `sk_sandbox_…` keys operate in a fully simulated **sandbox** (test cards,
      Base Sepolia crypto, no real money). The environment is derived from the
      key prefix.
  contact:
    email: contact@suby.fi
    url: https://suby.fi
servers:
  - url: https://api.beta.suby.fi
    description: Production + sandbox (environment selected by API key prefix)
security:
  - ApiKeyAuth: []
tags:
  - name: Products
    description: Manage your product catalog (one-time and recurring).
  - name: Checkout
    description: >-
      Hosted checkout · signed session tokens (`cs_…`). Every card Suby holds
      was collected here, which is what keeps card data out of your systems.
  - name: Payments
    description: >-
      Read payments and receipts, refund them, and debit a stored instrument
      off-session (pay-as-you-go). Collecting a card happens on the hosted
      checkout, never here.
  - name: Subscriptions
    description: >-
      Drive a live subscription · read it, change its plan, end it.
      Subscriptions are opened by a checkout session, not by this API.
  - name: Discount Codes
    description: Promo codes, redeemed at checkout.
  - name: Crypto
    description: >-
      The headless rail · quote, charge, and settle on-chain from inside your
      own site. No card data is involved, so none of the constraints that keep
      card collection on a Suby page apply here.
  - name: Customers
    description: First-class customer records with billing address.
  - name: Payment Methods
    description: >-
      Read and detach the cards a customer has stored. They are created by a
      checkout session (`savePaymentMethod`, or `mode=setup`) · the only place a
      card is collected.
  - name: Licence Key
    description: >-
      The licence server · validate a key, take a seat, free one. Authenticated
      with your API key like everything else, and scoped to the licences you
      issued, so your backend relays the check rather than your customer's
      software calling it directly.
paths:
  /v3/products/{id}/archive:
    post:
      tags:
        - Products
      summary: Take a product off sale
      description: |
        Move the product to `ARCHIVED`. It stops being sellable at checkout;
        subscriptions already running on it keep renewing.

        Nothing is ever deleted · past payments reference the row, and a receipt
        from last year still has to render. Empty body.
      operationId: archiveProduct
      parameters:
        - $ref: '#/components/parameters/ProductId'
        - $ref: '#/components/parameters/IdempotencyKey'
      responses:
        '200':
          description: Product archived
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SuccessEnvelope'
                  - properties:
                      data:
                        $ref: '#/components/schemas/Product'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  parameters:
    ProductId:
      name: id
      in: path
      required: true
      schema:
        type: string
        example: pro_abc123
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        Optional key (≤255 chars, e.g. a UUID v4) that makes this POST safe to
        retry: the first request executes and its response is cached for 24h; a
        retry with the SAME key replays that response instead of re-executing
        (no duplicate payment/subscription). A reused key with a different
        request → `422 IDEMPOTENCY_KEY_CONFLICT`; a retry while the first is
        still in flight → `409`. See the Idempotency guide.
      schema:
        type: string
        maxLength: 255
        example: 5f3b9c2e-1a4d-4f2b-9c31-7e2a1b6d8c04
  schemas:
    SuccessEnvelope:
      type: object
      required:
        - success
        - data
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
        data:
          description: Endpoint-specific payload.
    Product:
      type: object
      properties:
        id:
          type: string
          example: pro_abc123
        organizationId:
          type: string
        name:
          type: string
        description:
          type: string
          nullable: true
        imageUrl:
          type: string
          nullable: true
        status:
          type: string
          enum:
            - DRAFT
            - ACTIVE
            - ARCHIVED
        billingMode:
          type: string
          enum:
            - onetime
            - subscription
            - pay_as_you_go
          description: >-
            `onetime` / `subscription` = the product carries the price ·
            `pay_as_you_go` = each charge names its own amount.
        priceCents:
          type: string
          nullable: true
          description: Price in cents as a string of digits.
        currency:
          type: string
          nullable: true
          enum:
            - EUR
            - USD
        recurringInterval:
          type: string
          nullable: true
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
          description: >-
            The cadence of a subscription · non-null exactly when `billingMode`
            is `subscription`. Read the mode, not this field, to know what kind
            of product it is.
        recurringIntervalCount:
          type: integer
          nullable: true
        recurringCycleCount:
          type: integer
          nullable: true
          description: Cycle cap; null = open-ended.
        quantity:
          type: integer
          nullable: true
        consumedQuantity:
          type: integer
        taxInclusive:
          type: boolean
          description: >-
            `true` = the price is TTC (VAT extracted from it), `false` = HT (VAT
            added on top). Written through the `taxBehavior` field of
            create/update.
        customFields:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/CustomField'
        paymentMethods:
          $ref: '#/components/schemas/PaymentMethodOverride'
        successUrl:
          type: string
          format: uri
          nullable: true
        cancelUrl:
          type: string
          format: uri
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    CustomField:
      type: object
      required:
        - key
        - label
        - type
      properties:
        key:
          type: string
          maxLength: 50
          pattern: ^[a-z0-9_]+$
          description: Response-map key.
        label:
          type: string
          maxLength: 100
        type:
          type: string
          enum:
            - input
            - select
            - checkbox
        required:
          type: boolean
        placeholder:
          type: string
          maxLength: 200
        options:
          type: array
          description: Required (≥1) when `type=select`.
          items:
            type: object
            required:
              - value
              - label
            properties:
              value:
                type: string
                maxLength: 100
              label:
                type: string
                maxLength: 100
        validation:
          type: object
          description: '`type=input` only · client-side regex.'
          properties:
            regex:
              type: string
              maxLength: 500
            errorMessage:
              type: string
              maxLength: 200
        defaultValue:
          type: string
          maxLength: 500
          description: Merchant pre-fill (editable).
    PaymentMethodOverride:
      type: array
      nullable: true
      description: >-
        Per-product payment-method whitelist. `null` / `[]` / omitted = the
        product accepts every method enabled on the account. A non-empty list
        restricts checkout to these categories (always intersected with the
        account's enabled methods, so listing a disabled method is a harmless
        no-op).
      items:
        type: string
        enum:
          - CARD
          - APPLE_PAY
          - GOOGLE_PAY
          - KLARNA
          - IDEAL
          - BANCONTACT
          - TWINT
          - BLIK
          - AFFIRM
          - ALMA
          - BILLIE
          - SCALAPAY
          - MULTIBANCO
          - PAYPAL
          - SEPA_DIRECT_DEBIT
          - ACH_DIRECT_DEBIT
          - STABLECOIN
          - VOLATILE_CRYPTO
    Error:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          description: Machine-readable error code.
          example: NOT_FOUND
        message:
          type: string
          example: Resource not found
        data:
          description: Optional error detail.
  responses:
    Unauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            error: UNAUTHORIZED
            message: Invalid or missing API key
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            error: NOT_FOUND
            message: Resource not found
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Suby-Api-Key
      description: Secret API key. `sk_live_…` (production) or `sk_sandbox_…` (sandbox).

````