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

# Adicionar item ao plano

> Cria um item e o seu preço inicial na mesma chamada, num plano que já existe.

`POST /plans/:id/items`

Faz parte do recurso [Planos e Preços](/pt-BR/subscriptions/plans) — o item, o preço versionado e
os status estão lá.

Acrescenta uma linha de cobrança a um plano que já existe. O item e o seu primeiro preço nascem
juntos, e a validação roda sobre os dois antes de qualquer gravação — item sem preço não chega a
existir.

<Note>
  **Não se envia cadência nem período de teste.** Os dois são condições da oferta e vivem no plano;
  o preço do item novo os herda. É o que garante que dois itens recorrentes do mesmo plano nunca
  fiquem com datas de cobrança diferentes.
</Note>

<Warning>
  **A `key` não se repete entre os itens ativos do plano.** É o nome estável pelo qual a assinatura
  se refere ao item, e reusar uma que já está em uso responde `409`.

  **Arquivar um item libera a `key` dele** — o contrário do `code` do plano, que fica ocupado para
  sempre. Reusá-la cria um item novo, sem relação com o antigo: as assinaturas que já cobravam o
  item arquivado continuam nele, porque apontam para o identificador, não para a `key`. Se os dois
  cobram coisas diferentes, prefira uma `key` nova — senão dois itens distintos passam a ter o
  mesmo nome no seu catálogo.
</Warning>

<Warning>
  **Plano arquivado não recebe item.** A rota responde `409`: arquivar é terminal, e o plano vira
  somente leitura. Para uma oferta nova, publique um plano novo.
</Warning>

<Note>
  **Item `activation` nunca herda o período de teste.** Mesmo que o plano tenha `trialSpec`, a
  adesão é cobrada na primeira fatura — não há cobrança futura para diferir.
</Note>

<Note>
  **O item entra só nas assinaturas seguintes.** Quem já assinou instanciou o plano como ele era, e
  não passa a ser cobrado pelo item novo. O acréscimo vale para as assinaturas criadas a partir
  daqui.
</Note>

## Exemplo

```bash theme={null}
curl -X POST https://api.sandbox.z2pay.com/v1/plans/plan_lhutpqeq2ml3stia4vn90xars/items \
  -H "x-api-key: SUA_CHAVE_DE_SANDBOX" \
  -H "Content-Type: application/json" \
  -d '{
    "item": {
      "key": "suporte-premium",
      "name": "Suporte premium",
      "kind": "recurring",
      "quantityDefault": 1
    },
    "price": { "amount": 4900, "currency": "BRL" }
  }'
```

```json Resposta 201 theme={null}
{
  "id": "pli_x0hn9c2eqp7wl4tzka8m3vgdi",
  "planId": "plan_lhutpqeq2ml3stia4vn90xars",
  "key": "suporte-premium",
  "name": "Suporte premium",
  "kind": "recurring",
  "quantityDefault": 1,
  "displayOrder": 0,
  "description": null,
  "metadata": {},
  "currentPrice": {
    "id": "price_qm2v7ta6zj51ndkeb9urhwx4o",
    "planItemId": "pli_x0hn9c2eqp7wl4tzka8m3vgdi",
    "planId": "plan_lhutpqeq2ml3stia4vn90xars",
    "amount": 4900,
    "currency": "BRL",
    "billingScheme": "fixed",
    "isCurrent": true
  },
  "createdAt": "2026-08-10T15:10:00.000Z",
  "updatedAt": "2026-08-10T15:10:00.000Z"
}
```


## OpenAPI

````yaml openapi/billing.json POST /plans/{id}/items
openapi: 3.0.3
info:
  title: Z2Pay Billing API
  version: 1.0.0
  description: Cobrança recorrente da Z2Pay — planos, assinaturas e faturas
servers:
  - url: https://api.sandbox.z2pay.com/v1
    description: Sandbox
  - url: https://api.z2pay.com/v1
    description: Produção
security: []
tags:
  - name: Invoices
    description: Faturas emitidas pelas assinaturas
  - name: Plans
    description: Planos de cobrança e versões de preço
  - name: Subscriptions
    description: Assinaturas recorrentes
paths:
  /plans/{id}/items:
    post:
      tags:
        - Plans
      summary: Adicionar item ao plano
      description: >-
        Cria o item e seu preço inicial na mesma chamada. A validação roda sobre
        os dois antes de qualquer gravação — item sem preço não chega a existir.
        Item `kind=recurring` vira item da assinatura; `kind=activation` é
        cobrado uma vez, na fatura de adesão.
      operationId: PlanController_createItem
      parameters:
        - name: id
          in: path
          required: true
          description: ID do plano
          schema:
            type: string
        - name: Idempotency-Key
          in: header
          required: false
          description: Chave única para garantir idempotência da requisição
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                item:
                  type: object
                  properties:
                    key:
                      type: string
                      minLength: 1
                      maxLength: 100
                      pattern: ^[a-z0-9-_]+$
                      description: >-
                        Slug estável do item, único dentro do plano. É por ele
                        que a assinatura escolhe quais itens opcionais incluir.
                    name:
                      type: string
                      minLength: 1
                      maxLength: 255
                      description: Nome do item, como aparece na fatura.
                    kind:
                      type: string
                      enum:
                        - recurring
                        - activation
                      default: recurring
                      description: >-
                        `recurring` cobra todo ciclo; `activation` cobra uma
                        única vez, na adesão.
                    quantityDefault:
                      type: integer
                      minimum: 0
                      exclusiveMinimum: true
                      default: 1
                      description: >-
                        Quantidade cobrada quando a assinatura não informa
                        outra.
                    displayOrder:
                      type: integer
                      minimum: 0
                      default: 0
                      description: >-
                        Ordem em que o item aparece quando você consulta o
                        plano.
                    description:
                      type: string
                      maxLength: 1000
                      description: Descrição do item. Opcional.
                    metadata:
                      type: object
                      additionalProperties: {}
                      description: Objeto livre de chave/valor. Opcional.
                  required:
                    - key
                    - name
                  description: O item do plano — o que aparece na linha da fatura.
                price:
                  type: object
                  properties:
                    billingScheme:
                      type: string
                      enum:
                        - fixed
                      default: fixed
                      description: >-
                        Forma de cobrança. Hoje só `fixed` (valor fixo por
                        ciclo).
                    amount:
                      type: integer
                      minimum: 0
                      description: Valor da cobrança, em centavos (menor unidade da moeda).
                    currency:
                      type: string
                      enum:
                        - BRL
                      description: >-
                        Código de moeda ISO 4217. Hoje o único valor aceito é
                        'BRL'.
                      default: BRL
                  required:
                    - amount
                  description: 'O preço inicial desse item: quanto e com que cadência.'
              required:
                - item
                - price
      responses:
        '201':
          description: Item criado, com o preço em vigor
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: Identificador único do registro.
                  planId:
                    type: string
                    description: ID do plano ao qual o registro pertence.
                  key:
                    type: string
                    description: >-
                      Chave única e legível (slug) do componente dentro do
                      plano.
                  name:
                    type: string
                    description: Nome de exibição do plano ou do componente.
                  kind:
                    type: string
                    enum:
                      - recurring
                      - activation
                    description: >-
                      Natureza da cobrança: `recurring` cobra a cada ciclo;
                      `activation` cobra uma única vez, na fatura de adesão.
                  quantityDefault:
                    type: integer
                    description: >-
                      Quantidade padrão do componente ao instanciar a
                      assinatura.
                  displayOrder:
                    type: integer
                    description: Ordem de exibição do componente na listagem do plano.
                  description:
                    type: string
                    nullable: true
                    description: Descrição do item (item do plano ou linha da fatura).
                  metadata:
                    type: object
                    description: >-
                      Metadados livres (pares chave-valor) para uso do
                      integrador; não afeta o processamento.
                  createdAt:
                    type: string
                    format: date-time
                    description: Data e hora de criação do registro (ISO 8601).
                  updatedAt:
                    type: string
                    format: date-time
                    description: Data e hora da última atualização do registro (ISO 8601).
                  currentPrice:
                    type: object
                    nullable: true
                    properties:
                      id:
                        type: string
                        description: Identificador único do registro.
                      planItemId:
                        type: string
                        description: >-
                          ID do componente (plan item) ao qual o preço se
                          refere.
                      planId:
                        type: string
                        description: ID do plano ao qual o registro pertence.
                      billingScheme:
                        type: string
                        description: >-
                          Esquema de cobrança do preço: fixed, per_unit, tiered,
                          package ou metered.
                      amount:
                        type: integer
                        description: Valor do preço ou da linha, em centavos.
                      currency:
                        type: string
                        description: 'Moeda no padrão ISO 4217 (ex.: BRL).'
                      recurrence:
                        type: object
                        description: >-
                          Regra de recorrência (intervalo, unidade e âncora do
                          ciclo).
                      trialSpec:
                        type: object
                        nullable: true
                        description: >-
                          Configuração do período de teste (trial) do preço;
                          nula se sem trial.
                      isCurrent:
                        type: boolean
                        description: Indica se esta é a versão de preço atualmente vigente.
                      publishedAt:
                        type: string
                        format: date-time
                        nullable: true
                        description: >-
                          Data e hora em que a versão de preço foi publicada
                          (ISO 8601).
                      archivedAt:
                        type: string
                        format: date-time
                        nullable: true
                        description: >-
                          Data e hora em que a versão de preço foi arquivada;
                          nula se ainda vigente (ISO 8601).
                      createdAt:
                        type: string
                        format: date-time
                        description: Data e hora de criação do registro (ISO 8601).
                      updatedAt:
                        type: string
                        format: date-time
                        description: >-
                          Data e hora da última atualização do registro (ISO
                          8601).
                    description: Versão de preço vigente do item do plano.
              example:
                id: pli_n8e7y0yrg2frgqpktke850zqo
                planId: plan_lhutpqeq2ml3stia4vn90xars
                key: wine
                name: Monthly Wine Bottle
                kind: recurring
                quantityDefault: 1
                displayOrder: 2
                description: Add-on wine bottle each cycle
                metadata: {}
                createdAt: '2025-06-29T17:00:00.000Z'
                updatedAt: '2025-06-29T17:00:00.000Z'
                currentPrice:
                  id: price_hmy57z19gvf70wufibh1bqstb
                  planItemId: pli_n8e7y0yrg2frgqpktke850zqo
                  planId: plan_lhutpqeq2ml3stia4vn90xars
                  billingScheme: fixed
                  amount: 4900
                  currency: BRL
                  recurrence:
                    interval: 1
                    unit: month
                    anchor: subscription_start
                    collectionTiming: prepaid
                  trialSpec: null
                  isCurrent: true
                  publishedAt: '2025-06-29T17:00:00.000Z'
                  archivedAt: null
                  createdAt: '2025-06-29T17:00:00.000Z'
                  updatedAt: '2025-06-29T17:00:00.000Z'
        '400':
          description: Falha de validação no item ou no preço
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Identificador estável do erro. É por ele que você deve
                          ramificar, não pela mensagem.
                      message:
                        type: string
                        description: >-
                          Descrição legível. Pode mudar sem aviso e não deve ser
                          usada em condicional.
                      issues:
                        type: array
                        description: >-
                          Um item por campo rejeitado. Nunca vem vazio: se há
                          400 de validação, há pelo menos um.
                        items:
                          type: object
                          properties:
                            path:
                              type: string
                              description: >-
                                Campo que falhou. Vem vazio quando o erro é do
                                corpo como um todo.
                            message:
                              type: string
                              description: O que há de errado com esse campo.
              example:
                error:
                  code: VALIDATION_ERROR
                  message: Validation failed
                  issues:
                    - path: status
                      message: >-
                        Status inválido. Valores aceitos: pending,
                        waiting_payment, paid, refused, canceled, refunded
                    - path: startDate
                      message: >-
                        Data deve ser ISO 8601 com timezone (ex.:
                        2026-06-24T00:00:00Z)
        '401':
          description: Chave de API ausente, malformada ou inválida
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Identificador estável do erro. É por ele que você deve
                          ramificar, não pela mensagem.
                      message:
                        type: string
                        description: >-
                          Descrição legível. Pode mudar sem aviso e não deve ser
                          usada em condicional.
              example:
                error:
                  code: UNAUTHORIZED
                  message: Invalid API key
        '404':
          description: Plano não encontrado
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Identificador estável do erro. É por ele que você deve
                          ramificar, não pela mensagem.
                      message:
                        type: string
                        description: >-
                          Descrição legível. Pode mudar sem aviso e não deve ser
                          usada em condicional.
              example:
                error:
                  code: NOT_FOUND
                  message: Item not found
        '409':
          description: Já existe item com esta key neste plano
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Identificador estável do erro. É por ele que você deve
                          ramificar, não pela mensagem.
                      message:
                        type: string
                        description: >-
                          Descrição legível. Pode mudar sem aviso e não deve ser
                          usada em condicional.
              example:
                error:
                  code: CONFLICT
                  message: No refundable payment found
        '422':
          description: >-
            Idempotency-Key já usada com um corpo diferente. Use uma chave nova
            para uma operação diferente
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: >-
                      Mensagem do conflito de idempotência. Aqui `error` é
                      texto, não objeto — ramifique pelo status HTTP.
              example:
                error: Idempotency key already used with a different request body
      security:
        - apiKey: []
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: API Key da Credential (gerada no Backoffice)

````