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

# Primeiros passos

> Crie uma chave de API no painel, troque-a por um token Bearer e faça a sua primeira chamada autenticada em cinco minutos.

Em cinco minutos você sai de uma conta Ephra vazia para uma chamada autenticada respondendo `200`. São três passos: criar a chave no painel, trocá-la por um token e usar o token.

## O que você vai precisar

* Uma conta de vendedor na Ephra, com acesso ao painel em [app.ephra.io](https://app.ephra.io).
* `curl` e `jq` no terminal (qualquer cliente HTTP serve — os exemplos usam `curl`).

<Info>
  A URL base de produção é `https://api.ephra.io`. Não existe ambiente de sandbox público: as chamadas atingem a sua empresa de verdade. Comece por rotas de leitura (`GET`).
</Info>

## Passo 1 — Crie a chave de API

<Steps>
  <Step title="Abra o painel">
    Entre em [app.ephra.io](https://app.ephra.io) e vá em **Dashboard › Chaves de API** (`/dashboard/api-keys`).
  </Step>

  <Step title="Gere a chave">
    Clique em **Nova chave**, dê um nome que identifique o sistema que vai usá-la (por exemplo, `ERP da loja`) e confirme.
  </Step>

  <Step title="Guarde o par de credenciais">
    A tela mostra dois valores: o **público** (`api_token`) e o **secreto** (`api_secret`).

    <Warning>
      O valor secreto aparece **uma única vez**. Copie-o para um cofre de segredos antes de fechar a tela. Se perder, revogue a chave e gere outra.
    </Warning>
  </Step>
</Steps>

Exporte os dois no seu terminal para os próximos passos:

```bash theme={null}
export EPHRA_KEY="cmtxzjidu0000isg1f7pzbisr"
export EPHRA_SECRET="992a7d55bccbf39adfe6bec6259297a9..."
```

<Tip>
  Você pode conferir as chaves ativas da empresa pela própria API, em <a href="/api-reference/plataforma/listar-chaves-de-api">`GET /v1/api-keys`</a>. A resposta traz o `publicKey`, se a chave está `active` e quando foi criada — o segredo nunca volta.
</Tip>

## Passo 2 — Troque a chave por um token

A chave de API não autentica as rotas `/v1/*` diretamente. Ela serve para uma coisa só: pedir um token em `POST /auth`, usando **HTTP Basic** — o valor público como usuário, o secreto como senha.

```bash theme={null}
curl -s -X POST https://api.ephra.io/auth \
  -u "$EPHRA_KEY:$EPHRA_SECRET"
```

```json theme={null}
{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "tokenType": "Bearer",
  "expiresIn": 60000
}
```

Guarde o token numa variável:

```bash theme={null}
export TOKEN=$(curl -s -X POST https://api.ephra.io/auth \
  -u "$EPHRA_KEY:$EPHRA_SECRET" | jq -r .token)
```

<Warning>
  **O token dura 60 segundos em produção.** O campo `expiresIn` vem em milissegundos: `60000`. Não guarde o token em cache por horas nem o distribua entre processos — peça um novo sempre que for iniciar uma sequência de chamadas, e refaça o `POST /auth` quando receber `401`.
</Warning>

O motivo de o token ser tão curto é o mesmo de qualquer credencial de portador: quem tiver o token tem a empresa. Um minuto de janela transforma um vazamento em quase nada. A chave de API, essa sim, é de longo prazo — e por isso nunca sai do seu servidor.

## Passo 3 — Faça a primeira chamada

Com o token na mão, qualquer rota `/v1/*` aceita o header `Authorization: Bearer`. Comece pelo saldo, que é leitura pura:

```bash theme={null}
curl -s https://api.ephra.io/v1/balance \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "success": true,
  "data": {
    "available": 83470,
    "receivable": 0,
    "reserved": 0
  }
}
```

Os três campos são **inteiros em centavos**: `available` é o que dá para sacar agora, `receivable` o que ainda vai liberar e `reserved` o que está retido. `83470` é R\$ 834,70. Dinheiro nunca aparece como ponto flutuante nesta API.

Agora liste os seus produtos:

```bash theme={null}
curl -s "https://api.ephra.io/v1/products?page=1&pageSize=2" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "success": true,
  "data": [
    {
      "id": "cmtxxggxb0000vyg19j6v7qja",
      "name": "Curso de Tráfego Pago",
      "description": "Do primeiro anúncio ao primeiro real faturado.",
      "status": "approved",
      "categoryId": 1,
      "price": 49900,
      "productType": "digital",
      "billingType": "one_time",
      "deliveryType": "link",
      "imageUrl": null,
      "salesPage": "https://exemplo.com.br/trafego-pago",
      "productorName": null,
      "supportEmail": "suporte@exemplo.com.br",
      "supportPhone": null,
      "refundPeriodDays": 7,
      "createdAt": "2026-09-12T05:11:17.451Z",
      "updatedAt": "2026-09-12T05:51:19.286Z"
    }
  ],
  "pagination": { "page": 1, "pageSize": 2, "total": 6, "totalPages": 3 }
}
```

É esse o formato de toda lista da API do vendedor: `success`, `data` e `pagination`. Veja [Paginação, filtros e erros](/guias/paginacao-filtros-erros).

## Quando o `401` aparecer

<AccordionGroup>
  <Accordion title="Token inválido ou expirado">
    ```json theme={null}
    { "success": false, "message": "Token inválido ou expirado" }
    ```

    Passou dos 60 segundos, ou a sessão daquele login foi encerrada. Refaça o `POST /auth` e repita a chamada. Vale escrever isso uma vez no seu cliente HTTP: em `401`, reautentique e tente de novo, no máximo uma vez.
  </Accordion>

  <Accordion title="Credenciais inválidas no POST /auth">
    São **duas** respostas `401` diferentes, e elas dizem coisas diferentes:

    ```json theme={null}
    { "success": false, "message": "Credenciais inválidas." }
    ```

    O valor público existe, mas o secreto não confere — quase sempre é um segredo truncado na cópia.

    ```json theme={null}
    { "success": false, "message": "API key não encontrada" }
    ```

    O valor público não existe, ou a chave foi revogada no painel. Gere outra em **Dashboard › Chaves de API**; revogar não é reversível.
  </Accordion>

  <Accordion title="Esqueceu o Basic no POST /auth">
    `POST /auth` **não tem corpo**. As credenciais vão no header `Authorization: Basic`, que o `-u` do `curl` monta para você. Mandar um JSON com a chave dentro não autentica nada.
  </Accordion>
</AccordionGroup>

## Para onde ir agora

<CardGroup cols={2}>
  <Card title="Paginação, filtros e erros" icon="list-ol" href="/guias/paginacao-filtros-erros">
    O envelope de lista, os parâmetros `page`/`pageSize` e o formato de erro que toda rota compartilha.
  </Card>

  <Card title="Catálogo" icon="box" href="/guias/catalogo">
    Crie um produto, uma oferta e um cupom pela API.
  </Card>

  <Card title="Servidor MCP" icon="robot" href="/guias/mcp">
    Dê a API inteira para um agente de IA operar em linguagem natural.
  </Card>

  <Card title="Cobranças" icon="qrcode" href="/guias/pix">
    Gere um PIX ou uma cobrança no cartão.
  </Card>
</CardGroup>
