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

# IDs e recursos

> Formato dos identificadores e convenções de recursos da API.

A API do Repass segue um conjunto de convenções de plataforma que valem para **todos** os recursos: programas, afiliados, links, conversões, comissões, payouts e demais. Esta página descreve as quatro mais transversais: o formato dos identificadores, os timestamps duplos, as unidades monetárias inteiras e o isolamento multi-tenant. Conhecê-las uma vez é suficiente para ler qualquer resposta da API.

## Identificadores

Todo recurso tem um ID opaco no formato `<prefixo>_<ULID>`:

* O **prefixo** indica o tipo do recurso (`prog`, `aff`, `conv`...). Use-o para saber, só de olhar, o que um ID representa.
* O **corpo** é um [ULID](https://github.com/ulid/spec) de 26 caracteres no alfabeto Crockford `[0-9A-HJKMNP-TV-Z]` (sem as letras `I`, `L`, `O`, `U`).

```text theme={null}
prog_01J9Z3K7QF8XQ2M4VN6T0RBA9C
└──┘ └────────────────────────┘
 prefixo        ULID (26 chars)
```

<Note>
  Trate IDs como strings opacas. O comprimento total é estável (prefixo + `_` + 26 chars), mas não dependa de parsear o corpo: apenas armazene e devolva o valor exato que a API entregou.
</Note>

### IDs são ordenáveis por tempo

O ULID é gerado por uma factory monotônica, então a **ordenação lexicográfica dos IDs equivale à ordem de criação**. Isso tem duas consequências práticas:

* Listagens "mais recentes primeiro" usam `ORDER BY id DESC` no servidor.
* O próprio ID serve de cursor de paginação (`starting_after` / `ending_before`). Veja [Paginação](/docs/convencoes/paginacao).

### Catálogo de prefixos

Cada tipo de recurso tem um prefixo fixo. Os principais expostos pela API:

| Prefixo | Recurso                      | Conceito                                                 |
| ------- | ---------------------------- | -------------------------------------------------------- |
| `prog_` | Programa                     | [Programas e regras](/docs/conceitos/programas-e-regras)      |
| `cmrl_` | Regra de comissão            | [Programas e regras](/docs/conceitos/programas-e-regras)      |
| `tier_` | Faixa/tier de programa       | [Programas e regras](/docs/conceitos/programas-e-regras)      |
| `aff_`  | Afiliado                     | [Afiliados](/docs/conceitos/afiliados)                        |
| `term_` | Versão de termos             | [Termos](/docs/conceitos/termos)                              |
| `link_` | Link                         | [Links e cupons](/docs/conceitos/links-e-cupons)              |
| `coup_` | Cupom                        | [Links e cupons](/docs/conceitos/links-e-cupons)              |
| `clk_`  | Clique                       | [Tracking](/docs/conceitos/tracking)                          |
| `vis_`  | Visitor (identidade anônima) | [Tracking](/docs/conceitos/tracking)                          |
| `vid_`  | Identificação de visitor     | [Tracking](/docs/conceitos/tracking)                          |
| `conv_` | Conversão                    | [Conversões e fraude](/docs/conceitos/conversoes-e-fraude)    |
| `comm_` | Comissão                     | [Comissões](/docs/conceitos/comissoes)                        |
| `pay_`  | Payout                       | [Payouts](/docs/conceitos/payouts)                            |
| `inv_`  | Invoice / nota               | [Fiscal](/docs/conceitos/fiscal)                              |
| `repr_` | Job de reprocessamento       | [Reprocessamento](/docs/conceitos/reprocessamento)            |
| `rpit_` | Item de reprocessamento      | [Reprocessamento](/docs/conceitos/reprocessamento)            |
| `evt_`  | Evento de domínio            | [Event store](/docs/conceitos/event-store)                    |
| `whep_` | Endpoint de webhook          | [Webhooks: visão geral](/docs/webhooks/visao-geral)           |
| `whdl_` | Entrega de webhook           | [Retries e dead-letter](/docs/webhooks/retries-e-dead-letter) |
| `set_`  | Registro de configuração     | (uso interno)                                            |
| `idem_` | Registro de idempotência     | [Idempotência](/docs/convencoes/idempotencia)                 |

<Info>
  Os recursos de identidade (usuário, sessão, organização, API key) usam IDs próprios, **sem** prefixo de tipo. O padrão `<prefixo>_<ULID>` vale para os recursos de domínio listados acima.
</Info>

### Validação

Cada endpoint valida o prefixo esperado do ID que recebe. Um ID de outro tipo, ou com corpo malformado, é rejeitado com `400 parameter_invalid` antes mesmo de tocar a lógica de negócio.

```bash theme={null}
# Passar um aff_ onde se espera um prog_ é rejeitado
curl https://api.userepass.com/programs/aff_01J9Z3K7QF8XQ2M4VN6T0RBA9C \
  -H "Authorization: Bearer rstr_..."
```

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "Invalid program id",
    "param": "id"
  }
}
```

Para o catálogo completo de erros, veja [Erros](/docs/convencoes/erros).

## Timestamps

Todos os timestamps são UTC, em ISO 8601. Os recursos carregam **dois pares** distintos, dependendo do tipo:

### `createdAt` / `updatedAt`

Presentes na maioria dos recursos mutáveis:

* **`createdAt`**: quando o registro nasceu no Repass.
* **`updatedAt`**: quando foi alterado pela última vez (atualizado automaticamente a cada mudança).

```json theme={null}
{
  "id": "aff_01J9Z3K7QF8XQ2M4VN6T0RBA9C",
  "name": "Maria Silva",
  "status": "approved",
  "createdAt": "2026-06-13T14:02:11.000Z",
  "updatedAt": "2026-06-13T14:08:45.000Z"
}
```

### `occurredAt` / `recordedAt`

Recursos que representam um **fato com origem externa** (eventos, cliques, conversões, comissões) distinguem *quando o fato aconteceu* de *quando o sistema o gravou*:

* **`occurredAt`**: quando o fato aconteceu no mundo. Pode vir do gateway de pagamento ou do seu sistema (ex.: o instante real da cobrança). É a base de janelas de atribuição, hold de comissão e sinais de fraude.
* **`recordedAt`** (ou `createdAt`, conforme o recurso): quando o Repass gravou o fato. Sempre o relógio do servidor.

Os dois podem divergir: você pode enviar uma conversão hoje cujo `occurredAt` é de ontem. O Repass usa `occurredAt` para todas as decisões temporais de negócio.

```mermaid theme={null}
sequenceDiagram
    participant G as Gateway / seu sistema
    participant R as API Repass
    participant E as Event store
    G->>R: POST /conversions { occurredAt: ontem 09:00 }
    Note over R: decisões de negócio<br/>(atribuição, hold, fraude)<br/>usam occurredAt
    R->>E: grava evento
    Note over E: occurredAt = ontem 09:00 (fato)<br/>recordedAt = agora (servidor)
```

<Tip>
  Ao enviar conversões server-to-server, envie sempre o `occurredAt` real do fato. Omitir o campo faz o Repass assumir "agora", o que pode deslocar janelas de atribuição e o cálculo de hold. Veja [Conversões server-to-server](/docs/guias/conversoes-server-to-server).
</Tip>

## Unidades monetárias

O Repass nunca usa números de ponto flutuante para dinheiro ou percentuais. Há duas convenções inteiras:

### Dinheiro em centavos

Todo valor monetário é um **inteiro em centavos**. Os campos terminam em `Cents` (`amountCents`, `baseAmountCents`, `gatewayFeeCents`...).

| Valor      | Campo `*Cents` |
| ---------- | -------------- |
| R\$ 100,00 | `10000`        |
| R\$ 49,90  | `4990`         |
| R\$ 0,99   | `99`           |

### Percentuais em basis points

Percentuais são inteiros em **basis points** (bps), onde `10000 bps = 100%`. Os campos terminam em `Bps` (`percentageBps`, `weightBps`...).

| Percentual | Campo `*Bps` |
| ---------- | ------------ |
| 100%       | `10000`      |
| 20%        | `2000`       |
| 2,5%       | `250`        |
| 0,5%       | `50`         |

Exemplo de uma regra de comissão de 20% sobre R\$ 49,90:

```json theme={null}
{
  "rule": { "type": "percentage", "percentageBps": 2000 },
  "conversion": { "amountCents": 4990 },
  "commission": { "baseAmountCents": 4990, "amountCents": 998 }
}
```

<Warning>
  A aplicação de percentuais usa arredondamento *half-up* para o centavo mais próximo. `2000 bps` sobre `4990` resulta em `998` centavos (R\$ 9,98), não em uma fração. Faça seus próprios cálculos de conferência também em inteiros para bater com o servidor. Para o detalhe do cálculo, veja [Comissões](/docs/conceitos/comissoes).
</Warning>

## Multi-tenancy

A API é estritamente multi-tenant: todo recurso de domínio pertence a **exatamente uma organização** (o `organizationId`), e nenhuma consulta cruza os limites de uma organização.

Você **não envia** o `organizationId` nas requisições. Ele é resolvido a partir da sua credencial:

* **API key** (`Authorization: Bearer rstr_...`): a organização é a dona da chave.
* **Sessão de cookie**: a organização é a "ativa" da sessão.

```bash theme={null}
# A mesma chave sempre opera dentro da organização que a emitiu
curl https://api.userepass.com/affiliates \
  -H "Authorization: Bearer rstr_..."
```

Consequências práticas:

* Listagens já vêm filtradas pela sua organização: você nunca vê recursos de outro tenant.
* Pedir por ID um recurso de outra organização retorna `404 resource_not_found` (não `403`), para não vazar a existência de IDs alheios.
* A unicidade de chaves de idempotência também é por tenant: a mesma `Idempotency-Key` pode coexistir em organizações diferentes sem colidir. Veja [Idempotência](/docs/convencoes/idempotencia).

Para o setup de credenciais, veja [Autenticação](/docs/autenticacao).

## Próximos passos

<CardGroup cols={2}>
  <Card title="Paginação" icon="list-ol" href="/docs/convencoes/paginacao">
    Cursores baseados em ID e o envelope `{ data, hasMore }`.
  </Card>

  <Card title="Expand" icon="diagram-project" href="/docs/convencoes/expand">
    Materialize relacionamentos sob demanda com `expand[]`.
  </Card>

  <Card title="Idempotência" icon="rotate" href="/docs/convencoes/idempotencia">
    Reenvie POSTs com segurança usando `Idempotency-Key`.
  </Card>

  <Card title="Erros" icon="triangle-exclamation" href="/docs/convencoes/erros">
    O envelope de erro único e o catálogo de códigos.
  </Card>
</CardGroup>
