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

# Criar Cartão

Este endpoint permite tokenizar e salvar um cartão de crédito de forma segura. O cartão é criptografado e associado a um cliente específico, permitindo seu uso em futuros pagamentos.

## Casos de Uso

* **Salvar cartão** para pagamentos futuros
* **Tokenização segura** de dados sensíveis
* **Reutilização** em pagamentos recorrentes
* **Network Token** automático (Visa/Mastercard)

## Parâmetros Obrigatórios

<ParamField path="customer_id" type="string" required>
  UUID do cliente ao qual o cartão será associado
</ParamField>

<ParamField path="encrypted" type="string" required>
  Dados do cartão criptografados usando nossa biblioteca de tokenização frontend
</ParamField>

## Estrutura dos Dados Criptografados

O parâmetro `encrypted` deve conter os dados do cartão criptografados usando AES-256-CBC. O SDK envia o seguinte formato:

```json theme={null}
{
  "cardData": {
    "number": "4111111111111111",
    "holder": "JOAO SILVA",
    "expMonth": "12",
    "expYear": "2030",
    "securityCode": "123",
    "brand": "visa"
  },
  "cardHolder": {
    "name": "João Silva",
    "identification": {
      "type": "cpf",
      "number": "12345678900"
    }
  }
}
```

<Info>
  **cardHolder Opcional:** O objeto `cardHolder` é enviado pelo SDK mas **não é processado** pela API de cartões. Ele é utilizado apenas em integrações com gateways específicos. Para salvar cartões, apenas o `cardData` é necessário.
</Info>

<Warning>
  **Importante:** Nunca envie dados de cartão em texto puro. Use sempre o SDK (nossa biblioteca de tokenização frontend) para criptografar os dados antes de enviá-los para a API.
</Warning>

<Note>
  **Criptografia:** Os dados são criptografados no browser usando AES-256-CBC com a chave pública fornecida. O IV (Initialization Vector) é derivado do MD5 da chave secreta (primeiros 16 caracteres).
</Note>

## Exemplo de Requisição

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://pay.autorizou.dev/api/v1/cards \
    -H "Authorization: Bearer 4eC39HqLyjWDarjtT1zdp7dc" \
    -H "Content-Type: application/json" \
    -d '{
      "customer_id": "46e9d3d9-afb2-4d19-9a29-43b739f859a5",
      "encrypted": "eyJjYXJkRGF0YSI6eyJudW1iZXIiOiI0MTExMTExMTExMTExMTExIiwiaG9sZGVyIjoiSk9BTyBTSUxWQSIsImV4cE1vbnRoIjoiMTIiLCJleHBZZWFyIjoiMjAzMCIsInNlY3VyaXR5Q29kZSI6IjEyMyIsImJyYW5kIjoidmlzYSJ9fQ=="
    }'
  ```

  ```javascript JavaScript theme={null}
  // 1. Incluir o SDK (biblioteca de criptografia do Autorizou)
  // <script src="https://sdk.autorizou.dev/embed/gateway.js"></script>

  // 2. Preparar dados do cartão
  const cardData = {
    number: '4111111111111111',
    holder: 'JOAO SILVA',
    expMonth: '12',
    expYear: '2030',
    securityCode: '123'
  };

  // 3. Preparar dados do portador (opcional para salvar cartão)
  const cardHolder = {
    name: 'João Silva',
    identification: {
      type: 'CPF',
      number: '12345678900'
    }
  };

  // 4. Criptografar usando o SDK
  await window.Autorizou.encryptCard(
    { cardData, cardHolder },
    {
      onSuccess: async (response) => {
        // 5. Enviar token criptografado para a API
        const apiResponse = await fetch('https://pay.autorizou.dev/api/v1/cards', {
          method: 'POST',
          headers: {
            'Authorization': 'Bearer 4eC39HqLyjWDarjtT1zdp7dc',
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            customer_id: 'cus_abc123def456ghi789',
            encrypted: response.token
          })
        });

        const card = await apiResponse.json();
        console.log('Cartão tokenizado:', card);
      },
      onError: (error) => {
        console.error('Erro na criptografia:', error);
      }
    }
  );
  ```

  ```php PHP theme={null}
  <?php

  // Assumindo que os dados já foram criptografados no frontend
  $encryptedCardData = 'eyJjYXJkRGF0YSI6eyJudW1iZXIiOiI0MTExMTExMTExMTExMTExIiwiaG9sZGVyIjoiSk9BTyBTSUxWQSIsImV4cE1vbnRoIjoiMTIiLCJleHBZZWFyIjoiMjAzMCIsInNlY3VyaXR5Q29kZSI6IjEyMyIsImJyYW5kIjoidmlzYSJ9fQ==';

  $data = [
      'customer_id' => 'cus_abc123def456ghi789',
      'encrypted' => $encryptedCardData
  ];

  $curl = curl_init();
  curl_setopt_array($curl, [
      CURLOPT_URL => 'https://pay.autorizou.dev/api/v1/cards',
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_POST => true,
      CURLOPT_HTTPHEADER => [
          'Authorization: Bearer 4eC39HqLyjWDarjtT1zdp7dc',
          'Content-Type: application/json'
      ],
      CURLOPT_POSTFIELDS => json_encode($data)
  ]);

  $response = curl_exec($curl);
  $card = json_decode($response, true);
  curl_close($curl);

  echo "Cartão criado: " . json_encode($card, JSON_PRETTY_PRINT);
  ?>
  ```
</CodeGroup>

## Resposta de Sucesso

### Cartão Novo (201 Created)

Quando um novo cartão é criado com sucesso:

```json theme={null}
{
  "id": "3f7d2a91-8c4e-4b6f-9a2d-5e8c1f4b7a30",
  "customer_id": "46e9d3d9-afb2-4d19-9a29-43b739f859a5",
  "holder": "JOAO SILVA",
  "brand": "visa",
  "first_6": "411111",
  "last_4": "1111",
  "exp_month": "12",
  "exp_year": "30",
  "created_at": "15/01/2024 10:35:00",
  "updated_at": "15/01/2024 10:35:00"
}
```

<Note>
  **Network Token:** Para cartões Visa e Mastercard, um Network Token é automaticamente solicitado em segundo plano. O processo de tokenização acontece de forma assíncrona e não impacta a resposta inicial.
</Note>

### Cartão Duplicado (200 OK)

Se um cartão idêntico já existe para o cliente (mesmo número, nome, validade e bandeira) e já foi usado em um pagamento autorizado:

```json theme={null}
{
  "id": "b96e2d54-7a3c-4f8e-91d6-4e7a2c5f8b19",
  "customer_id": "46e9d3d9-afb2-4d19-9a29-43b739f859a5",
  "holder": "JOAO SILVA",
  "brand": "visa",
  "first_6": "411111",
  "last_4": "1111",
  "exp_month": "12",
  "exp_year": "30",
  "created_at": "10/01/2024 08:20:00",
  "updated_at": "10/01/2024 08:20:00"
}
```

<Warning>
  **Detecção de Duplicatas:** O sistema detecta cartões duplicados baseado em: mesmo cliente + mesmo número (first\_6 + last\_4) + mesmo nome + mesma validade + mesma bandeira + ter sido usado em pagamento autorizado.
</Warning>

## Detalhes da Resposta

| Campo         | Tipo   | Descrição                                                       |
| ------------- | ------ | --------------------------------------------------------------- |
| `id`          | string | UUID único do cartão tokenizado                                 |
| `customer_id` | string | UUID do cliente proprietário                                    |
| `holder`      | string | Nome do portador do cartão                                      |
| `brand`       | string | Bandeira detectada automaticamente (visa, mastercard, elo, etc) |
| `first_6`     | string | Primeiros 6 dígitos do cartão (BIN)                             |
| `last_4`      | string | Últimos 4 dígitos do cartão                                     |
| `exp_month`   | string | Mês de expiração (MM)                                           |
| `exp_year`    | string | Ano de expiração (YY) - apenas 2 dígitos                        |
| `created_at`  | string | Data de criação no formato DD/MM/YYYY HH:mm:ss                  |
| `updated_at`  | string | Data da última atualização                                      |

### Network Token (Visa e Mastercard)

Para cartões Visa e Mastercard, o sistema solicita automaticamente a criação de um Network Token através do VGS (Very Good Security). Este processo ocorre de forma assíncrona após a criação do cartão.

**Benefícios do Network Token:**

* Maior taxa de aprovação em pagamentos
* Melhor segurança (token dinâmico)
* Atualização automática de dados de expiração
* Redução de fraudes

<Info>
  **Processo Assíncrono:** A solicitação do Network Token não bloqueia a resposta da API. O token é gerado em segundo plano e associado ao cartão posteriormente.
</Info>

## Códigos de Erro

<AccordionGroup>
  <Accordion title="422 - Validation Error" icon="circle-xmark">
    Erro de validação nos dados fornecidos

    ```json theme={null}
    {
      "error": {
        "code": "validation_error",
        "message": "Os dados fornecidos são inválidos",
        "details": {
          "customer_id": ["Cliente não encontrado"],
          "encrypted": ["Dados criptografados inválidos"]
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="400 - Invalid Encrypted Data" icon="circle-xmark">
    Dados criptografados malformados ou inválidos

    ```json theme={null}
    {
      "error": {
        "code": "invalid_encrypted_card",
        "message": "Dados do cartão criptografados são inválidos"
      }
    }
    ```

    **Possíveis causas:**

    * Criptografia incorreta
    * Dados corrompidos
    * Formato JSON inválido nos dados descriptografados
  </Accordion>

  <Accordion title="404 - Customer Not Found" icon="circle-xmark">
    Cliente não encontrado

    ```json theme={null}
    {
      "error": {
        "code": "customer_not_found",
        "message": "Cliente não encontrado"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Detecção de Duplicatas

O sistema detecta automaticamente cartões duplicados para evitar a criação de cartões redundantes. A duplicata é identificada quando todas as condições abaixo são atendidas:

**Critérios de Duplicata:**

* **Mesmo cliente** (`customer_id`)
* **Mesmo número** (`first_6` e `last_4`)
* **Mesmo portador** (`holder`)
* **Mesma validade** (`exp_month` e `exp_year`)
* **Mesma bandeira** (`brand_id`)
* **Cartão já usado** em pagamento autorizado (status `AUTHORIZED`)

**Comportamento quando detectada duplicata:**

* **Não cria** novo cartão
* **Retorna** cartão existente
* **Status HTTP 200** (em vez de 201)

<Tip>
  **Otimização:** Esta verificação evita sobrecarga no banco de dados e no sistema de tokenização, além de simplificar a gestão de cartões para o usuário final.
</Tip>

## Bandeiras Suportadas

| Bandeira   | Network Token | Detecção Automática |
| ---------- | ------------- | ------------------- |
| Visa       | Sim           | Sim                 |
| Mastercard | Sim           | Sim                 |
| Elo        | Não           | Sim                 |
| Hipercard  | Não           | Sim                 |
| Diners     | Não           | Sim                 |
| Discover   | Não           | Sim                 |
| JCB        | Não           | Sim                 |
| Amex       | Não           | Sim                 |

<Note>
  **Network Token:** Apenas cartões Visa e Mastercard suportam Network Token. Para outras bandeiras, o cartão é tokenizado normalmente através do VGS.
</Note>

## Implementação Frontend com SDK

### Instalação do SDK

O SDK é a biblioteca oficial do Autorizou para criptografia de dados de cartão no frontend.

```html theme={null}
<!-- Incluir SDK via CDN -->
<script src="https://sdk.autorizou.dev/embed/gateway.js"></script>
```

<Note>
  **Ambiente de Teste:** Para desenvolvimento, você pode usar a versão de sandbox. Configure a variável de ambiente `NEXT_PUBLIC_APP_ENV` para controlar o ambiente.
</Note>

### Exemplo Completo de Integração

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <title>Exemplo SDK - Tokenização de Cartão</title>
  <!-- 1. Incluir SDK -->
  <script src="https://sdk.autorizou.dev/embed/gateway.js"></script>
</head>
<body>
  <!-- 2. Formulário de cartão -->
  <form id="card-form">
    <div>
      <label>Número do Cartão</label>
      <input type="text" id="card-number" placeholder="0000 0000 0000 0000" maxlength="19">
    </div>
    <div>
      <label>Nome no Cartão</label>
      <input type="text" id="card-holder" placeholder="NOME COMPLETO">
    </div>
    <div>
      <label>Validade (MM/AAAA)</label>
      <input type="text" id="card-month" placeholder="12" maxlength="2">
      <input type="text" id="card-year" placeholder="2030" maxlength="4">
    </div>
    <div>
      <label>CVV</label>
      <input type="text" id="card-cvv" placeholder="123" maxlength="4">
    </div>
    <button type="submit">Salvar Cartão</button>
  </form>

  <script>
    // 3. Handler do formulário
    document.getElementById('card-form').addEventListener('submit', async (e) => {
      e.preventDefault();

      // 4. Coletar dados do formulário
      const cardData = {
        number: document.getElementById('card-number').value.replace(/\s/g, ''),
        holder: document.getElementById('card-holder').value.toUpperCase(),
        expMonth: document.getElementById('card-month').value,
        expYear: document.getElementById('card-year').value,
        securityCode: document.getElementById('card-cvv').value
      };

      const cardHolder = {
        name: document.getElementById('card-holder').value,
        identification: {
          type: 'CPF',
          number: '00000000000' // Opcional: adicione campo no formulário se necessário
        }
      };

      try {
        // 5. Criptografar com o SDK usando callbacks
        await window.Autorizou.encryptCard(
          { cardData, cardHolder },
          {
            onSuccess: async (encryptResponse) => {
              // 6. Enviar para o backend
              const response = await fetch('https://pay.autorizou.dev/api/v1/cards', {
                method: 'POST',
                headers: {
                  'Authorization': 'Bearer 4eC39HqLyjWDarjtT1zdp7dc',
                  'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                  customer_id: 'cus_abc123def456ghi789',
                  encrypted: encryptResponse.token
                })
              });

              const result = await response.json();

              if (response.ok) {
                alert('Cartão salvo com sucesso! ID: ' + result.id);
                document.getElementById('card-form').reset();
              } else {
                alert('Erro ao salvar cartão: ' + (result.message || 'Erro desconhecido'));
              }
            },
            onError: (error) => {
              alert('Erro na criptografia: ' + (error.message || 'Erro desconhecido'));
            }
          }
        );

      } catch (error) {
        console.error('Erro:', error);
        alert('Erro ao processar cartão: ' + error.message);
      }
    });
  </script>
</body>
</html>
```

### Integração React/Next.js

```jsx theme={null}
import { useState } from 'react';

export default function CardForm({ customerId }) {
  const [cardData, setCardData] = useState({
    number: '',
    holder: '',
    expMonth: '',
    expYear: '',
    securityCode: ''
  });
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    setError(null);

    try {
      // Verificar se o SDK está disponível
      if (!window.Autorizou?.encryptCard) {
        throw new Error('SDK não está carregado. Verifique se o script foi incluído.');
      }

      // Preparar cardHolder (opcional para salvar cartão)
      const cardHolder = {
        name: cardData.holder,
        identification: {
          type: 'CPF',
          number: '00000000000' // Opcional: adicione ao formulário se necessário
        }
      };

      // Criptografar dados do cartão usando callbacks
      await window.Autorizou.encryptCard(
        { cardData, cardHolder },
        {
          onSuccess: async (encryptResponse) => {
            try {
              // Enviar para a API
              const response = await fetch('https://pay.autorizou.dev/api/v1/cards', {
                method: 'POST',
                headers: {
                  'Authorization': `Bearer ${process.env.NEXT_PUBLIC_AUTORIZOU_API_KEY}`,
                  'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                  customer_id: customerId,
                  encrypted: encryptResponse.token
                })
              });

              const result = await response.json();

              if (!response.ok) {
                throw new Error(result.message || 'Erro ao salvar cartão');
              }

              alert('Cartão salvo com sucesso!');
              setCardData({ number: '', holder: '', expMonth: '', expYear: '', securityCode: '' });
            } catch (err) {
              setError(err.message);
              console.error('Erro ao salvar cartão:', err);
            } finally {
              setLoading(false);
            }
          },
          onError: (error) => {
            setError(error.message || 'Erro na criptografia');
            console.error('Erro na criptografia:', error);
            setLoading(false);
          }
        }
      );

    } catch (err) {
      setError(err.message);
      console.error('Erro:', err);
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        placeholder="Número do cartão"
        value={cardData.number}
        onChange={(e) => setCardData({ ...cardData, number: e.target.value })}
        required
      />
      <input
        type="text"
        placeholder="Nome no cartão"
        value={cardData.holder}
        onChange={(e) => setCardData({ ...cardData, holder: e.target.value.toUpperCase() })}
        required
      />
      <input
        type="text"
        placeholder="Mês (MM)"
        value={cardData.expMonth}
        onChange={(e) => setCardData({ ...cardData, expMonth: e.target.value })}
        maxLength="2"
        required
      />
      <input
        type="text"
        placeholder="Ano (AAAA)"
        value={cardData.expYear}
        onChange={(e) => setCardData({ ...cardData, expYear: e.target.value })}
        maxLength="4"
        required
      />
      <input
        type="text"
        placeholder="CVV"
        value={cardData.securityCode}
        onChange={(e) => setCardData({ ...cardData, securityCode: e.target.value })}
        maxLength="4"
        required
      />

      {error && <div style={{ color: 'red' }}>{error}</div>}

      <button type="submit" disabled={loading}>
        {loading ? 'Processando...' : 'Salvar Cartão'}
      </button>
    </form>
  );
}
```

```jsx theme={null}
// No seu _app.js ou layout.js
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        {/* Carregar SDK */}
        <Script
          src={`https://sdk.autorizou.${
            process.env.NEXT_PUBLIC_AUTORIZOU_ENVIRONMENT === 'live' ? 'cloud' : 'dev'
          }/embed/gateway.js`}
          strategy="beforeInteractive"
        />
      </head>
      <body>{children}</body>
    </html>
  );
}
```

## Segurança e Compliance

<Warning>
  **PCI DSS:** Este endpoint atende aos requisitos PCI DSS. Dados sensíveis nunca trafegam em texto puro e são imediatamente tokenizados.
</Warning>

<Note>
  **Criptografia End-to-End:** Os dados são criptografados no browser do usuário e apenas descriptografados nos servidores seguros da Autorizou.
</Note>

## Próximos Passos

Após criar um cartão:

1. [Processar pagamento com o cartão](/api-reference/charges/orders/create-order)
2. [Buscar detalhes do cartão](/api-reference/cards/get-card)
3. [Solicitar Network Token (Visa/Mastercard)](/api-reference/cards/enroll-network-token)
4. [Integração frontend com SDK](/api-reference/cards/card-tokenization)
