<!-- Source: https://docs.infraio.xyz/pt-BR/api-reference/authentication -->
<!-- Last updated: 2026-10-04 -->

# Autenticação

A InfraIO Pay tem **duas superfícies de API** com modelos de
autenticação diferentes. Escolha a que combina com quem está
chamando:

| Superfície | Prefixo do path | Audiência | Auth |
| --- | --- | --- | --- |
| **B2B do lojista** | `/b2b/v1/*` | Seu servidor | Assinatura de requisição HMAC-SHA256 |
| **Dashboard** | Usada pelo dashboard do lojista | Sessões de navegador para o dashboard do lojista | Bearer JWT |

Esta página cobre a superfície **B2B**, a que você chama do seu
servidor com um par de chaves de API. A superfície do dashboard é usada
pelo dashboard do lojista da InfraIO Pay e não é uma superfície pública de
integração.

Envie sempre o path completo, incluindo o prefixo `/b2b`, e assine esse
mesmo path (veja abaixo).

## Endpoints

| Ambiente | Base URL |
| --- | --- |
| Teste | `https://api-dev.infraio.xyz` |
| Live | `https://api.infraio.xyz` |

Mesmo padrão de URL — o ambiente é controlado pelo **prefixo da
chave** (`pk_test_…` vs `pk_live_…`), não pela URL.

## Par de chaves

Você pega dois valores no dashboard do lojista (**Developers → API
keys → + Add key**):

- **Chave publicável** (`pk_test_…` ou `pk_live_…`) — identifica a
  sua conta. Enviada como `X-Client-ID`. Seguro embutir no seu
  bundle do navegador (o SDK já faz isso).
- **Chave secreta** (`sk_test_…` ou `sk_live_…`) — a chave de
  assinatura HMAC. Só servidor. Trate como uma senha de banco de
  dados.

> **Important:**
>
> Se uma chave secreta cair num bundle de navegador, repo git,
> linha de log ou chat compartilhado — **revogue imediatamente** no
> dashboard. A revogação é instantânea, sem janela de sobreposição.
> Crie uma chave nova e redeploye.

## Assinando uma requisição

Toda chamada para `/b2b/v1/*` leva três headers:

```http
X-Client-ID:  pk_live_70d0becbd7a53047b0dfe88a960d10ad
X-Timestamp:  1715990400
X-Signature:  9a8b7c6d…             (hex HMAC-SHA256)
```

A assinatura é calculada sobre uma string canônica:

```
METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + BODY
```

- `METHOD` — verbo HTTP em maiúsculas (`POST`, `GET`, …).
- `PATH` — path da requisição **incluindo o prefixo `/b2b`**, sem o
  host e **sem a query string** (por exemplo,
  `/b2b/v1/checkout-sessions/quick`). O prefixo precisa estar
  presente. Parâmetros de query **não** são assinados — para um
  `GET …?cursor=…&limit=20`, assine só o path, não a parte `?…`.
- `TIMESTAMP` — unix segundos, como string decimal (por exemplo,
  `"1715990400"`), batendo exatamente com o `X-Timestamp`.
- `BODY` — bytes brutos do body da requisição. String vazia para
  `GET`/`DELETE`.

Assine com HMAC-SHA256 chaveado pela chave **secreta**, saída
**hex**:

**Node / TS**

```ts
import { createHmac } from "node:crypto";

function sign({ method, path, body, secret }: {
  method: string; path: string; body: string; secret: string;
}) {
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const input = [method.toUpperCase(), path, timestamp, body].join("\n");
  const signature = createHmac("sha256", secret).update(input).digest("hex");
  return { timestamp, signature };
}
```

**Go**

```go
package infraio

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "strconv"
    "time"
)

func Sign(method, path, body, secret string) (timestamp, signature string) {
    timestamp = strconv.FormatInt(time.Now().Unix(), 10)
    input := method + "\n" + path + "\n" + timestamp + "\n" + body
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write([]byte(input))
    return timestamp, hex.EncodeToString(mac.Sum(nil))
}
```

**Python**

```python
import hmac, hashlib, time

def sign(method: str, path: str, body: str, secret: str):
    timestamp = str(int(time.time()))
    input_ = f"{method}\n{path}\n{timestamp}\n{body}"
    signature = hmac.new(
        secret.encode(), input_.encode(), hashlib.sha256
    ).hexdigest()
    return timestamp, signature
```

## Por que HMAC, e não Bearer?

Uma API de token Bearer puro envia o seu único segredo pela rede em
toda requisição. Quem capturar um log de proxy com terminação TLS
ganha as chaves da sua conta. Assinar com HMAC significa que o
segredo nunca viaja — só a assinatura derivada dele, que é de uso
único (vinculada àquela requisição exata + aquele minuto exato).

O trade-off: você calcula uma assinatura a cada chamada. Ainda não
há um SDK de servidor, mas o helper acima tem cerca de 15 linhas por
linguagem.

## Tolerância do timestamp

A tolerância é de **±5 minutos** (300 segundos). Uma requisição fora
dessa janela é rejeitada com `401 invalid_signature`. Duas
implicações:

1. **Sincronize o relógio do seu servidor** via NTP. Um cron de
   longa duração com relógio desviado vai falhar
   intermitentemente.
2. **Não pré-compute e enfileire assinaturas.** Se uma requisição
   fica numa fila de retry por mais de 5 min, a assinatura expira.

## Escopos de chave

Chaves secretas carregam um ou mais destes bundles de escopo:

| Escopo | Uso pretendido |
| --- | --- |
| `read` | Listar/ler pedidos, sessões, reembolsos |
| `write_order` | Criar sessões de checkout, pedidos |
| `write_refund` | Emitir reembolsos, criar tokens de pedido de reembolso |
| `webhook_manage` | Criar/atualizar/deletar endpoints de webhook |

O dashboard emite uma chave "full access" por padrão (os quatro
escopos). Você pode criar uma chave com escopo restrito em
**Developers → API keys → + Add key** e marcar só os escopos que a
integração precisa.

> **Warning:**
>
> **Os escopos ainda não são aplicados.** Os escopos são registrados na
> chave e exibidos no dashboard, mas qualquer chave `sk_…` válida pode
> chamar qualquer endpoint `/b2b/v1/*` do seu lojista. Não conte com os
> escopos como fronteira de segurança. Rotacione ou revogue chaves para
> restringir o acesso.

## Falha na verificação

Se a assinatura, o `X-Client-ID` ou o timestamp forem inválidos, a
requisição é rejeitada com **401 `INVALID_SIGNATURE`** antes de chegar
à API. Somente as requisições `/b2b/v1/*` são assinadas dessa forma.
Os webhooks usam um esquema separado (veja abaixo).

## Próximos passos

- [Erros](https://docs.infraio.xyz/pt-BR/api-reference/errors) — formato da resposta em
  4xx/5xx.
- [Segurança → Chaves de API](https://docs.infraio.xyz/pt-BR/security/api-keys) — rotação,
  revogação, o que fazer se um segredo vaza.
- [Webhooks → Verificação de assinatura](https://docs.infraio.xyz/pt-BR/webhooks/signature-verification)
  — usa um esquema HMAC *diferente* (header `X-Signature: sha256=…`,
  assina `X-Timestamp + "." + raw_body`, mais um `X-Signature-Prev`
  opcional durante a janela de tolerância de 24 horas da rotação).
  Não misture os esquemas — eles compartilham o algoritmo de hash
  mas os bytes assinados e a família de segredos (`whsec_…` vs
  `sk_…`) são diferentes.
