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

# Início rápido

> Uma chamada HTTP e você tem tenant, chave de teste e sandbox — sem instalar nada.

Você não precisa de conta, cartão nem CLI pra começar. Uma chamada HTTP cria um
tenant de sandbox e devolve as chaves de teste. Você assume a conta depois,
dentro do prazo retornado em `expiresAt`.

Integrando com IA? Comece pelo [cadastro pelo agente](/agent-onboarding).
Ele pergunta email, nome do app e forma de cobrança, prepara o ambiente e entrega
o link para você finalizar na Infi.

## 1. Pegue uma chave

```bash theme={null}
curl -X POST https://api-sandbox.beinfi.com/public/v1/claimables \
  -H 'Content-Type: application/json' \
  -d '{"email":"founder@example.com","accountName":"Acme"}'
```

Resposta (`201`):

```json theme={null}
{
  "id": "d4147638-938e-4854-a6f7-3addaac7909a",
  "status": "UNCLAIMED",
  "tenantSlug": "app-ec62ff27",
  "accountName": "Acme",
  "productId": "95165eab-a189-43eb-b2b9-83c714cb204e",
  "apiKeySecret": "sk_test_09eed9fc…",
  "publishableKey": "pk_test_…",
  "claimUrl": "https://app-sandbox.beinfi.com/claim/d4147638-938e-4854-a6f7-3addaac7909a",
  "expiresAt": "2026-10-04T19:49:46Z"
}
```

* `apiKeySecret` — sua `sk_test_`. Vem **uma única vez**, não tem como reemitir.
* `publishableKey` — sua `pk_test_` da Infi, para APIs de cliente que a exigem. A chave secreta continua no servidor.
* `tenantSlug` — o `slug` que entra na URL pública de cobrança (`/pay/{slug}/…`).
* `claimUrl` — abra pra assumir a conta. O prazo padrão é de 30 dias; vale a data de `expiresAt`.
* `productId` — o produto seed. Ele **não serve pra vender nem pra medir ainda**:
  vem sem `key`, sem meter e com a versão 1 em `draft`. O seu produto de verdade
  você cria em <a href="/catalogo">catálogo</a>.

`email` e `accountName` são opcionais. O corpo também aceita `ref` (`{"ref":"cli"}`)
pra marcar a origem. Com a atualização de email de claim, informar o endereço
enfileira um aviso com link e prazo, limitado a um por endereço a cada 24 horas.
Guarde e entregue a `claimUrl` mesmo assim: `201` não confirma entrega do email.
O endereço só vira contato; assumir a conta exige login.

<Warning>
  **Não mande `intent` nesse endpoint.** `{"intent":"one-time"}` responde `422 unrecognized field`. Intent é conceito da
  CLI, não do endpoint público.
</Warning>

## O atalho: uma linha e você já tem o que vender

O curl acima te dá a chave e um produto que **não serve pra vender**. A CLI faz a
corrente inteira:

```bash theme={null}
npx -y @beinfi/cli bootstrap --intent one-time --ref cli --json
```

Medido, numa pasta vazia: além do tenant e da chave, ela deixa um produto
`item` + `one_time` com a **versão publicada** a R\$ 29,90 — e "publicar" é o passo
que ninguém adivinha e que faz a diferença entre um produto cobrável e um `422`.
Dá pra faturar nele imediatamente, sem mais nenhuma chamada:

```ts theme={null}
await infi.invoices.createForProduct(productId, { customer: {…} });
// -> { status: "open", total: "29.90" }
```

Ela também escreve `infi.company.ts` + `.env.local`, sincroniza e roda `doctor`.

Se você fizer à mão, são cinco chamadas — criar produto, listar versões, publicar,
inscrever cliente, faturar — e todas estão em
<a href="/catalogo">catálogo</a>. Vale ler de qualquer jeito pra saber
o que a CLI fez por você; só não precisa digitar.

<Info>
  **Só a chave, sem escrever arquivo.** `npx -y @beinfi/cli claim create --json`. E desde a `0.2.0` a CLI deduz o host a
  partir do prefixo da chave — em versões anteriores as duas falhavam sem
  `INFI_API_URL`, então se você tiver uma presa em lockfile, atualize.
</Info>

## 2. Hosts

Nada disso precisa ir pro env do seu app — o SDK resolve host a partir do prefixo
da chave. Escreva aqui pra quem usa curl, libera egress ou debuga DNS:

|                  | sandbox (`sk_test_`)     | produção (`sk_live_`) |
| ---------------- | ------------------------ | --------------------- |
| API              | `api-sandbox.beinfi.com` | `api.beinfi.com`      |
| Checkout / links | `app-sandbox.beinfi.com` | `app.beinfi.com`      |

<Info>
  **curl: Idempotency-Key.** Todo `POST`/`PUT`/`DELETE` autenticado exige o header `Idempotency-Key` — sem ele
  volta `400 idempotency_key_required`. O SDK gera um por chamada. (O
  `/public/v1/claimables` do passo 1 é exceção: é público e não pede.)
</Info>

## 3. Variáveis de ambiente

```bash theme={null}
INFI_SECRET_KEY=sk_test_...   # obrigatória (servidor)
INFI_PUBLISHABLE_KEY=pk_test_... # APIs de cliente que exigem a chave pública Infi
INFI_TENANT_SLUG=seu-tenant   # slug do checkout hospedado /pay/{slug}
APP_URL=https://seu-app.com   # origens / redirects (recomendado)
```

<Warning>
  **Não use URLs legacy.** `INFI_AUTH_BASE_URL` e `INFI_PAY_BASE_URL` são legado — o SDK nem lê essas
  variáveis, e `infi doctor` pede pra remover. O host de API e o de checkout saem
  do prefixo da chave: `sk_test_` → `api-sandbox` + `app-sandbox`, `sk_live_` →
  `api` + `app`. Pra apontar pra outro lugar (local, self-host), use `apiUrl` /
  `appUrl` no construtor.
</Warning>

## 4. Instale o SDK

<Tabs>
  <Tab title="npm">
    ```bash theme={null}
    npm install @beinfi/sdk
    ```
  </Tab>

  <Tab title="pnpm">
    ```bash theme={null}
    pnpm add @beinfi/sdk
    ```
  </Tab>

  <Tab title="bun">
    ```bash theme={null}
    bun add @beinfi/sdk
    ```
  </Tab>
</Tabs>

```ts theme={null}
import { Infi } from "@beinfi/sdk";

export const infi = new Infi({ secretKey: process.env.INFI_SECRET_KEY! });

await infi.products.list(); // sanity check: a chave responde
```

## 5. Medir uso

Medição precisa de um produto **seu**, com meter e versão publicada — três
chamadas em <a href="/catalogo">catálogo</a>. Com isso pronto, inscreva
o seu usuário no produto e registre uso:

```ts theme={null}
// seuUserId vem do SEU auth — a Infi não faz login de usuário final
const enrollment = await infi.products.enroll(productId, {
  externalId: seuUserId,
  email: "cliente@empresa.com",
});

await infi.track({
  customerId: enrollment.id,   // id da inscrição, não o seu id de usuário
  productId,                   // obrigatório quando o tenant tem >1 produto
  meter: "tokens",
  value: "1200",
});
```

<Warning>
  **`enroll` não abre período — e sem período não há crédito.** `products.enroll` cria a inscrição e para aí. O grant `on: "cycle"` só é
  creditado quando um período **abre**, e quem abre período é a assinatura:

  ```ts theme={null}
  await infi.products.subscribe(productId, { enrollmentId: enrollment.id });
  ```

  Sem isso a carteira fica em zero e toda chamada com gate pré-pago cai em `402`,
  com o catálogo perfeitamente configurado.
</Warning>

<Warning>
  **Dois 422 comuns em `track`.** `productId: is required` — o tenant já tem o produto seed, então basicamente
  sempre há mais de um produto: mande `productId` sempre. E `meter: unknown meter`
  — o meter tem que existir no produto antes (veja catálogo).
</Warning>

## Próximos passos

<CardGroup cols={2}>
  <Card title="Catálogo" href="/catalogo">
    Produto → versão publicada → preço. É o que falta antes de cobrar.
  </Card>

  <Card title="Saber que pagou" href="/webhooks">
    Webhooks em produção, polling em sandbox.
  </Card>

  <Card title="Sua primeira venda" href="/primeira-venda">
    Do zero à fatura paga: qual caminho escolher e o que guardar.
  </Card>

  <Card title="Company as code" href="/company-as-code">
    Catálogo declarado em git.
  </Card>
</CardGroup>
