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

# Loja e moedas

> A economia interna da Cativa: moedas ganhas por engajamento e trocadas por itens na loja, com um ciclo de pedido que integra com fulfillment externo.

<Note>
  Moedas e loja são a camada de **gamificação com valor real**. O usuário acumula moedas participando da comunidade e as troca por itens numa loja. O diferencial da Cativa é que o **pedido tem um ciclo de vida** que você conecta ao seu próprio fulfillment (enviar um brinde físico, liberar um cupom, disparar uma integração).
</Note>

## Os dois lados

```
MOEDAS (Wallets)                          LOJA (Store)
carteira do usuário       ──troca por──>  itens da loja
saldo + extrato                           pedido (order)

Ganho de moedas:                          Ciclo do pedido:
- engajamento na comunidade               criado ──> approve / reject
- crédito via admin/integração                    ──> fulfill / refund
```

**Moedas** são a economia interna. O usuário ganha moedas por engajamento e você também pode creditar saldo via admin ou integração (ex: bônus por compra externa). **A loja** troca esse saldo por itens. Cada resgate vira um **pedido**, e o pedido passa por um ciclo que é o gancho de integração para o fulfillment.

Pense nas moedas como os tíquetes de um parque de diversões: o visitante ganha tíquetes brincando e os troca por um brinde no balcão de prêmios. O **pedido** é o comprovante do balcão; aprovar, entregar o brinde e (se faltou no estoque) devolver os tíquetes são as etapas que você controla.

## Base URL e autenticação

Todas as rotas ficam na **API da Cativa**:

```
https://apis.cativalab.digital/tenant/api/v2
```

Autentique com sua API Key no header:

```
Authorization: Bearer cativa_live_...
```

<Warning>
  Nunca exponha sua API Key no frontend nem a comite no repositório. Use `YOUR_API_KEY` como placeholder e injete o valor real por variável de ambiente.
</Warning>

## Moedas (Wallets)

O saldo e o extrato vivem na carteira do usuário.

| Rota                               | O que faz                              |
| ---------------------------------- | -------------------------------------- |
| `GET /monetization/wallet/coins`   | Saldo de moedas do usuário             |
| `GET /monetization/wallet/history` | Extrato (histórico de ganhos e gastos) |

Do lado admin, você credita saldo e consulta a carteira de qualquer usuário (por id ou por email). Veja os endpoints e os campos exatos na API Reference, tag **Wallets**.

### Consultar o saldo do usuário

<CodeGroup>
  ```bash cURL theme={null}
  curl https://apis.cativalab.digital/tenant/api/v2/monetization/wallet/coins \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```js Node theme={null}
  const res = await fetch(
    "https://apis.cativalab.digital/tenant/api/v2/monetization/wallet/coins",
    {
      headers: { Authorization: `Bearer ${process.env.YOUR_API_KEY}` },
    }
  );

  const wallet = await res.json();
  ```
</CodeGroup>

Resposta ilustrativa (o schema autoritativo fica na API Reference, tag **Wallets**). `balance` é o saldo de moedas do usuário, em unidades inteiras:

```json theme={null}
{
  "balance": 1250
}
```

<Note>
  A estrutura exata da resposta (nomes dos campos de saldo, moeda, extrato) está na API Reference. Consulte as tags **Wallets** e **Store** em vez de assumir o shape aqui.
</Note>

## Loja (Store)

O usuário navega pelas lojas, vê os itens e resgata com moedas.

| Rota                                                | O que faz                 |
| --------------------------------------------------- | ------------------------- |
| `GET /monetization/stores`                          | Lista as lojas            |
| `GET /monetization/stores/{storeId}/items`          | Itens de uma loja         |
| `GET /monetization/stores/items/{itemId}`           | Detalhe de um item        |
| `POST /monetization/stores/items/{itemId}/purchase` | Resgata o item com moedas |
| `GET /monetization/stores/my-orders`                | Pedidos do usuário        |

Os IDs (`storeId`, `itemId`, `orderId`) são **ULID**.

Do lado admin, você gerencia lojas e itens e opera os pedidos:

* `POST /admin/monetization/stores` · `PUT` / `DELETE /admin/monetization/stores/{storeId}`
* `POST /admin/monetization/stores/{storeId}/items` · `PUT` / `DELETE /admin/monetization/stores/items/{itemId}`
* `GET /admin/monetization/stores/orders` · `GET /admin/monetization/stores/orders/{orderId}`

## O ciclo do pedido

Quando o usuário resgata um item, nasce um pedido. Esse pedido percorre um ciclo, e cada transição é uma ação admin:

```
criado ──> approve  ──> fulfill
       └─> reject       └─> refund
```

* **approve / reject**: você valida o resgate (estoque, elegibilidade, antifraude) e aprova ou recusa.
* **fulfill**: você marca o pedido como entregue. Esse é o ponto onde o **fulfillment externo** acontece: enviar o brinde físico, gerar o cupom, chamar sua integração de logística.
* **refund**: devolve as moedas ao usuário quando o item não pode ser entregue.

As ações admin de pedido ficam em:

* `POST /admin/monetization/stores/orders/{orderId}/approve`
* `POST /admin/monetization/stores/orders/{orderId}/reject`
* `POST /admin/monetization/stores/orders/{orderId}/fulfill`
* `POST /admin/monetization/stores/orders/{orderId}/refund`

O fluxo típico de um resgate, do clique do usuário ao fechamento:

<Steps>
  <Step title="Usuário resgata">
    `POST /monetization/stores/items/{itemId}/purchase` debita as moedas e cria o pedido em estado inicial.
  </Step>

  <Step title="Você valida e aprova">
    `POST /admin/monetization/stores/orders/{orderId}/approve` (ou `reject`) depois de checar estoque, elegibilidade e antifraude.
  </Step>

  <Step title="Você entrega e conclui">
    Rode seu fulfillment externo (enviar o brinde, gerar o cupom) e feche com `POST .../fulfill`.
  </Step>

  <Step title="Se algo falhar, devolva">
    `POST .../refund` estorna as moedas ao usuário quando o item não pode ser entregue.
  </Step>
</Steps>

<Tip>
  Trate `fulfill` como o webhook da sua operação. Ao aprovar um pedido, dispare seu processo de entrega; ao concluir a entrega externa, chame `fulfill` para fechar o ciclo. Se a entrega falhar, use `refund` para devolver as moedas.
</Tip>

### Aprovar e concluir um pedido

<CodeGroup>
  ```bash cURL theme={null}
  # 1. aprova o resgate
  curl -X POST \
    https://apis.cativalab.digital/tenant/api/v2/admin/monetization/stores/orders/01J8Z9K3M4N5P6Q7R8S9T0V1W2/approve \
    -H "Authorization: Bearer YOUR_API_KEY"

  # 2. após entregar o item externamente, marca como concluído
  curl -X POST \
    https://apis.cativalab.digital/tenant/api/v2/admin/monetization/stores/orders/01J8Z9K3M4N5P6Q7R8S9T0V1W2/fulfill \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```js Node theme={null}
  const base =
    "https://apis.cativalab.digital/tenant/api/v2/admin/monetization/stores/orders";
  const orderId = "01J8Z9K3M4N5P6Q7R8S9T0V1W2";
  const headers = { Authorization: `Bearer ${process.env.YOUR_API_KEY}` };

  // 1. aprova o resgate
  await fetch(`${base}/${orderId}/approve`, { method: "POST", headers });

  // 2. após entregar o item externamente, marca como concluído
  await fetch(`${base}/${orderId}/fulfill`, { method: "POST", headers });
  ```
</CodeGroup>

Resposta ilustrativa de um pedido após `approve` (o schema autoritativo fica na API Reference, tag **Store**). O `status` reflete a etapa do ciclo:

```json theme={null}
{
  "orderId": "01J8Z9K3M4N5P6Q7R8S9T0V1W2",
  "status": "approved",
  "itemId": "01J8ITEM4567890ABCDEFGHJKM",
  "userId": "01HQ0USER1234567890ABCDEF",
  "coinsSpent": 500,
  "createdAt": "2026-07-10T14:00:00Z"
}
```

<Note>
  Os campos de resposta de cada rota (status do pedido, valores, timestamps) estão na API Reference, tags **Store** e **Wallets**. Não assuma o shape a partir dos exemplos acima.
</Note>

## Erros comuns e dúvidas

<AccordionGroup>
  <Accordion title="O resgate falhou por saldo insuficiente">
    `purchase` só cria o pedido se o usuário tem moedas suficientes para o item. Sem saldo, a chamada é recusada e nenhum pedido nasce. Consulte `GET /monetization/wallet/coins` antes, ou credite saldo pelo endpoint admin (tag **Wallets**) se a regra do seu programa permitir.
  </Accordion>

  <Accordion title="O pedido travou em aprovado e nunca foi entregue">
    `approve` só valida o resgate; ele não entrega nada sozinho. A entrega é o **seu** fulfillment externo, e é você quem chama `fulfill` ao concluir. Um pedido aprovado e nunca `fulfill`-ado fica em aberto de propósito, esperando sua operação fechar o ciclo.
  </Accordion>

  <Accordion title="As moedas foram debitadas mas o item não pôde ser entregue">
    Use `refund`. Ele estorna as moedas do pedido de volta à carteira do usuário. É a saída correta quando o estoque acabou ou a integração de logística falhou depois do débito.
  </Accordion>

  <Accordion title="Chamei approve duas vezes, dobrou alguma coisa?">
    As transições de pedido são idempotentes por estado: reaplicar `approve` num pedido já aprovado não cria um segundo pedido nem debita de novo. Isso torna seguro dar retry nas ações admin em jobs.
  </Accordion>

  <Accordion title="Quero liberar acesso a um grupo, não entregar um item físico">
    A loja entrega **itens**; ela não é o mecanismo de acesso. Para liberar grupo, curso ou espaço, use **badge como permissão** (veja [badges como permissão](/pt-BR/concepts/badges-as-permissions)). Moedas e acesso são camadas separadas.
  </Accordion>
</AccordionGroup>

## Como isso se conecta

* Para **creditar moedas** por uma ação externa (compra, indicação, brinde), use os endpoints admin de crédito por id ou email (tag **Wallets**).
* Para **liberar acesso** em vez de entregar item físico, o mecanismo é outro: veja [badges como permissão](/pt-BR/concepts/badges-as-permissions).
* Para entender **quem é o usuário** dono da carteira e do pedido, veja [identidade e usuários](/pt-BR/concepts/identity-and-users).
