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

# Autenticação

## Visão Geral

A API Cakto utiliza o protocolo OAuth2 para autenticar requisições. Neste guia, você aprenderá como obter um token de acesso e usá-lo para autenticar suas chamadas à API.

## Fluxo de Autenticação

Esse é o fluxo básico para autenticar suas requisições, mais adiante detalharemos cada etapa:

<Steps>
  <Step title="Criar Chave de API">
    Crie uma Chave de API (`client_id` e `client_secret`) no painel da Cakto
  </Step>

  <Step title="Solicitar Token">
    Envie uma requisição POST para o endpoint de token com suas credenciais
  </Step>

  <Step title="Usar Token">
    Inclua o token de acesso no header `Authorization` de cada requisição
  </Step>
</Steps>

## 1 - Criando Chaves de API

Para começar a usar a API Cakto, você precisa criar suas chaves de API. Siga estas etapas:

1. Acesse o [painel da Cakto](https://app.cakto.com.br/dashboard/cakto-api) e navegue até a seção **Integrações** depois **Cakto API**.

   <Frame caption="Painel Cakto: Integrações depois Cakto API.">
     <img src="https://i.ibb.co/hPWjcWP/menu-cakto-api.png" alt="Menu Integrações com Cakto API selecionado" />
   </Frame>

2. Clique em **“Criar Chave de API”**.

3. Preencha o formulário com um nome descritivo e selecione os [escopos](#escopos-de-acesso) de acesso necessários.

   <Frame caption="Modal de criação da Chave de API com a seleção de escopos.">
     <img src="https://i.ibb.co/GfzbvD8Z/escopos.png" alt="Modal Criar Chave API com seleção de escopos" />
   </Frame>

4. Salve o `client_id` e o `client_secret` gerados após finalizar a criação, especialmente o **client\_secret** que será exibido apenas nesse momento da criação.

## 2 - Solicitando Token de Acesso

Use este endpoint para trocar suas credenciais de API por um token de acesso OAuth2.

```bash theme={null}
    https://api.cakto.com.br/public_api/token/
```

#### Headers

<ParamField header="Content-Type" default="application/x-www-form-urlencoded" type="string" required placeholder="application/x-www-form-urlencoded">
  application/x-www-form-urlencoded
</ParamField>

#### Parâmetros do Corpo

<ParamField body="client_id" type="string" required>
  O identificador único da sua aplicação
</ParamField>

<ParamField body="client_secret" type="string" required>
  A chave secreta da sua aplicação (Fornecido apenas no momento da criação da chave de API)
</ParamField>

#### Exemplo de Requisição

<CodeGroup>
  ```bash curl icon=terminal lines theme={null}
  curl -X POST https://api.cakto.com.br/public_api/token/ \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "client_id=abc123xyz789" \
    -d "client_secret=secret_abc123xyz789def456" \
  ```

  ```python Python icon=python lines theme={null}
  import requests

  url = "https://api.cakto.com.br/public_api/token/"
  data = {
      "client_id": "abc123xyz789",
      "client_secret": "secret_abc123xyz789def456",
  }
  headers = {
      "Content-Type": "application/x-www-form-urlencoded"
  }

  response = requests.post(url, data=data, headers=headers)
  token_info = response.json()

  print(f"Access Token: {token_info['access_token']}")
  print(f"Expira em: {token_info['expires_in']} segundos")
  ```

  ```javascript JavaScript icon=square-js lines theme={null}
  const getToken = async () => {
    const response = await fetch('https://api.cakto.com.br/public_api/token/', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: new URLSearchParams({
        client_id: 'abc123xyz789',
        client_secret: 'secret_abc123xyz789def456',
      })
    });

    const tokenInfo = await response.json();
    return tokenInfo;
  };

  const tokenInfo = await getToken();
  console.log('Access Token:', tokenInfo.access_token);
  console.log('Expira em:', tokenInfo.expires_in, 'segundos');
  ```

  ```php PHP icon=php lines theme={null}
  <?php
  $url = "https://api.cakto.com.br/public_api/token/";

  $data = [
      'client_id' => 'abc123xyz789',
      'client_secret' => 'secret_abc123xyz789def456',
  ];

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Content-Type: application/x-www-form-urlencoded'
  ]);

  $response = curl_exec($ch);
  curl_close($ch);

  $tokenInfo = json_decode($response, true);
  echo "Access Token: " . $tokenInfo['access_token'];
  ?>
  ```
</CodeGroup>

#### Resposta de Sucesso (200 OK)

```json theme={null}
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "expires_in": 36000,
  "token_type": "Bearer",
  "scope": "read write products offers orders"
}
```

<ResponseField name="access_token" type="string">
  Token JWT que deve ser usado no header Authorization das requisições
</ResponseField>

<ResponseField name="expires_in" type="integer">
  Tempo de validade do token em segundos (exemplo: 36000 = 10 horas)
</ResponseField>

<ResponseField name="token_type" type="string">
  Tipo do token, sempre "Bearer"
</ResponseField>

<ResponseField name="scope" type="string">
  Escopos de acesso concedidos ao token, separados por espaço. Exemplo: `read write products`
</ResponseField>

#### Erros Comuns

<AccordionGroup>
  <Accordion title="401 Unauthorized - Credenciais Inválidas">
    ```json theme={null}
    {
      "error": "invalid_client"
    }
    ```

    **Solução**: Verifique se seu `client_id` e `client_secret` estão corretos
  </Accordion>

  <Accordion title="400 Bad Request - Escopo Inválido">
    ```json theme={null}
    {
      "error": "invalid_scope"
    }
    ```

    **Solução**: Use apenas escopos configurados na sua chave de API
  </Accordion>
</AccordionGroup>

## 3 - Usando o Token de Acesso

Após obter o token, inclua-o no header `Authorization` de todas as requisições à API:

```http theme={null}
Authorization: Bearer {access_token}
```

### Exemplo de Requisição Autenticada

<CodeGroup>
  ```bash curl icon=terminal lines theme={null}
  curl -X GET https://api.cakto.com.br/public_api/products/ \
    -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..."
  ```

  ```python Python icon=python lines theme={null}
  import requests

  access_token = "eyJ0eXAiOiJKV1QiLCJhbGc..."

  response = requests.get(
      "https://api.cakto.com.br/public_api/products/",
      headers={"Authorization": f"Bearer {access_token}"}
  )

  products = response.json()
  ```

  ```javascript JavaScript icon=square-js lines theme={null}
  const accessToken = "eyJ0eXAiOiJKV1QiLCJhbGc...";

  const response = await fetch('https://api.cakto.com.br/public_api/products/', {
    headers: {
      'Authorization': `Bearer ${accessToken}`
    }
  });

  const products = await response.json();
  ```
</CodeGroup>

### Expiração do Token

Tokens de acesso expiram após determinado tempo, retornado na [resposta de autenticação](#resposta-de-sucesso-200-ok) no campo `expires_in`. Após a expiração, outro token deve ser solicitado, **não** existe um endpoint para renovação.

### Escopos de Acesso

Os escopos controlam quais recursos e operações sua aplicação pode acessar:

| Escopo          | Descrição             | Permissões                                             |
| --------------- | --------------------- | ------------------------------------------------------ |
| `read`          | Leitura               | Permite consultar recursos (GET)                       |
| `write`         | Escrita               | Permite criar e modificar recursos (POST, PUT, DELETE) |
| `products`      | Produtos              | Acesso ao gerenciamento de produtos                    |
| `offers`        | Ofertas               | Acesso ao gerenciamento de ofertas                     |
| `orders`        | Pedidos               | Acesso à consulta de pedidos                           |
| `subscriptions` | Assinaturas           | Acesso ao gerenciamento de assinaturas                 |
| `webhooks`      | Webhooks              | Acesso ao gerenciamento de webhooks                    |
| `card_tokens`   | Tokenização de Cartão | Permite tokenizar cartões pelo SDK                     |
| `payments`      | Pagamentos            | Permite criar cobranças (Pix, boleto, cartão)          |

Os scopos `read` e `write` definem o nível de permissão do token, para leitura `read` e/ou escrita `write`.

Outros escopos como `products` e `offers` definem quais recursos específicos o token pode acessar.

### Segurança

<Warning>
  **Importante**: Nunca exponha suas credenciais em código cliente ou repositórios públicos!
</Warning>

### Melhores Práticas

<AccordionGroup>
  <Accordion title="Armazenamento Seguro de Credenciais" icon="lock">
    * Armazene `client_secret` em variáveis de ambiente
    * Nunca commite credenciais no controle de versão (git)
    * Armazene tokens de forma segura, não exponha em código client-side
  </Accordion>

  <Accordion title="Princípio do Menor Privilégio" icon="key">
    * Solicite apenas os escopos necessários
    * Crie chaves de API separadas para diferentes aplicações
    * Revise e atualize permissões regularmente
  </Accordion>
</AccordionGroup>

## Exemplos de Clientes

<AccordionGroup>
  <Accordion title="Python">
    ```python icon=python lines theme={null}
    import requests
    from typing import Optional

    class CaktoAPIClient:
      def __init__(self, client_id: str, client_secret: str):
          self.client_id = client_id
          self.client_secret = client_secret
          self.base_url = "https://api.cakto.com.br"
          self.access_token: Optional[str] = None
      
      def authenticate(self):
          """Obtém um novo access token"""
          url = f"{self.base_url}/public_api/token/"
          data = {
              "client_id": self.client_id,
              "client_secret": self.client_secret,
          }
          
          response = requests.post(url, data=data)
          response.raise_for_status()
          
          token_data = response.json()
          self.access_token = token_data["access_token"]
          
          return token_data
      
      def get_headers(self) -> dict:
          """Retorna headers com autenticação"""
          if not self.access_token:
              self.authenticate()
          
          return {
              "Authorization": f"Bearer {self.access_token}",
              "Content-Type": "application/json"
          }
      
      def get(self, endpoint: str, **kwargs):
          """Faz uma requisição GET"""
          url = f"{self.base_url}{endpoint}"
          response = requests.get(url, headers=self.get_headers(), **kwargs)
          response.raise_for_status()
          return response.json()
      
      def post(self, endpoint: str, data: dict, **kwargs):
          """Faz uma requisição POST"""
          url = f"{self.base_url}{endpoint}"
          response = requests.post(
              url, 
              headers=self.get_headers(), 
              json=data, 
              **kwargs
          )
          response.raise_for_status()
          return response.json()

    # Uso
    client = CaktoAPIClient(
        client_id="seu_client_id",
        client_secret="seu_client_secret"
    )

    # Listar produtos
    products = client.get("/public_api/products/")
    print(f"Total de produtos: {products['count']}")
    ```
  </Accordion>

  <Accordion title="JavaScript/TypeScript">
    ```typescript icon=square-js lines theme={null}
      class CaktoAPIClient {
        private baseUrl = 'https://api.cakto.com.br';
        private accessToken?: string;

        constructor(
          private clientId: string,
          private clientSecret: string
        ) {}

        async authenticate(): Promise<void> {
          const response = await fetch(`${this.baseUrl}/public_api/token/`, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: new URLSearchParams({
              client_id: this.clientId,
              client_secret: this.clientSecret,
            }),
          });

          if (!response.ok) {
            throw new Error(`Authentication failed: ${response.statusText}`);
          }

          const tokenData = await response.json();
          this.accessToken = tokenData.access_token;
        }

        private async getHeaders(): Promise<HeadersInit> {
          if (!this.accessToken) {
            await this.authenticate();
          }

          return {
            'Authorization': `Bearer ${this.accessToken}`,
            'Content-Type': 'application/json',
          };
        }

        async get<T>(endpoint: string): Promise<T> {
          const response = await fetch(`${this.baseUrl}${endpoint}`, {
            method: 'GET',
            headers: await this.getHeaders(),
          });

          if (!response.ok) {
            throw new Error(`GET request failed: ${response.statusText}`);
          }

          return response.json();
        }

        async post<T>(endpoint: string, data: any): Promise<T> {
          const response = await fetch(`${this.baseUrl}${endpoint}`, {
            method: 'POST',
            headers: await this.getHeaders(),
            body: JSON.stringify(data),
          });

          if (!response.ok) {
            throw new Error(`POST request failed: ${response.statusText}`);
          }

          return response.json();
        }
      }

      // Uso
      const client = new CaktoAPIClient(
        'seu_client_id',
        'seu_client_secret'
      );

      // Listar produtos
      const products = await client.get('/public_api/products/');
      console.log(`Total de produtos: ${products.count}`);
    ```
  </Accordion>
</AccordionGroup>

## Próximos Passos

<CardGroup cols={2}>
  <Card title="Introdução" icon="book-open" href="/introduction">
    Voltar para a visão geral da API
  </Card>

  <Card title="Referência da API" icon="book" href="/api-reference/products/list">
    Explore todos os endpoints disponíveis
  </Card>
</CardGroup>
