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

# Visão Geral da API

> Documentação completa da API REST do Testly para integração customizada

<Warning>
  **API em desenvolvimento.** O endpoint público `api.testly.com` ainda não está disponível. Para integrações hoje, use o [SDK React](/sdk/installation) (React/Next.js) ou entre em contato via [suporte@testly.com.br](mailto:suporte@testly.com.br) para acesso antecipado.
</Warning>

## Introdução

A API REST do Testly permitirá integrar experimentação A/B em qualquer aplicação, independente do framework ou linguagem.

### Quando usar a API diretamente?

* ✅ Você está usando um framework não suportado (Vue, Svelte, Angular)
* ✅ Precisa de integração server-side
* ✅ Quer construir sua própria camada de abstração
* ✅ Está migrando de outra ferramenta

### Quando usar o SDK React?

* ✅ Você está usando React, Next.js ou Remix
* ✅ Quer começar rápido sem configuração
* ✅ Precisa de gerenciamento automático de estado

<Tip>
  **Recomendação**: Se você usa React, prefira o [SDK oficial](/sdk/installation). Ele já implementa boas práticas de cache, retry e error handling.
</Tip>

***

## Base URL

```
https://lfhltqrtfwxoirjmhcdz.supabase.co/functions/v1
```

As Edge Functions do Testly ficam hospedadas no Supabase (região São Paulo). Todas as requisições devem usar HTTPS.

***

## Autenticação

A API do Testly usa **API Keys** para autenticação.

Inclua sua chave no header `x-testly-auth`:

```bash theme={null}
x-testly-auth: YOUR_API_KEY
```

### Obter sua API Key

1. Acesse o [dashboard do Testly](https://app.testly.com.br/)
2. Vá em **Configurações** → **Chave de API**
3. Copie sua chave (começa com `tk_live_` para produção ou `tk_test_` para desenvolvimento)

<Warning>
  **Segurança**: Nunca exponha sua API Key em código client-side público. Use variáveis de ambiente.
</Warning>

### Exemplo de Requisição

```bash theme={null}
curl "https://lfhltqrtfwxoirjmhcdz.supabase.co/functions/v1/get-variant?experiment_key=meu-experimento&user_id=user_123" \
  -H "x-testly-auth: tk_live_..."
```

***

## Rate Limits

| Plano    | Impressões/mês |
| -------- | -------------- |
| **Free** | 10.000         |
| **Pro**  | 100.000        |

Ao atingir o limite de impressões mensais, o SDK continua funcionando mas novas impressões param de ser registradas — conversões nunca são bloqueadas.

***

## Estrutura da Resposta

### Sucesso

Requisições bem-sucedidas retornam JSON com status `2xx`:

```json theme={null}
{
  "success": true,
  "data": {
    // Dados da resposta
  }
}
```

### Erro

Erros retornam JSON com status `4xx` ou `5xx`:

```json theme={null}
{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "A API Key fornecida é inválida",
    "details": {}
  }
}
```

***

## Códigos de Status HTTP

| Código                      | Descrição                            |
| --------------------------- | ------------------------------------ |
| `200 OK`                    | Requisição bem-sucedida              |
| `201 Created`               | Recurso criado com sucesso           |
| `400 Bad Request`           | Parâmetros inválidos                 |
| `401 Unauthorized`          | API Key ausente ou inválida          |
| `403 Forbidden`             | Sem permissão para acessar o recurso |
| `404 Not Found`             | Recurso não encontrado               |
| `429 Too Many Requests`     | Rate limit excedido                  |
| `500 Internal Server Error` | Erro no servidor (contacte suporte)  |

***

## Códigos de Erro Comuns

### INVALID\_API\_KEY

```json theme={null}
{
  "code": "INVALID_API_KEY",
  "message": "A API Key fornecida é inválida ou expirou"
}
```

**Solução**: Verifique se sua API Key está correta no dashboard.

### EXPERIMENT\_NOT\_FOUND

```json theme={null}
{
  "code": "EXPERIMENT_NOT_FOUND",
  "message": "Experimento não encontrado"
}
```

**Solução**: Verifique se o `experimentId` existe e está ativo.

### MISSING\_REQUIRED\_FIELD

```json theme={null}
{
  "code": "MISSING_REQUIRED_FIELD",
  "message": "Campo obrigatório ausente",
  "details": {
    "field": "userId"
  }
}
```

**Solução**: Inclua todos os campos obrigatórios na requisição.

***

## Recursos Principais

A API do Testly oferece os seguintes recursos:

### 1. Experimentos

Gerenciar experimentos A/B:

* `GET /experiments` - Listar todos os experimentos
* `GET /experiments/:id` - Obter detalhes de um experimento
* `POST /experiments` - Criar novo experimento
* `PATCH /experiments/:id` - Atualizar experimento
* `DELETE /experiments/:id` - Deletar experimento

### 2. Variantes

Atribuir e gerenciar variantes:

* `POST /variants/assign` - Atribuir variante para um usuário
* `GET /variants/:id` - Obter detalhes de uma variante

### 3. Eventos

Registrar impressões e conversões:

* `POST /events/impression` - Registrar impressão
* `POST /events/conversion` - Registrar conversão

***

## Exemplo: Fluxo Completo

Aqui está um exemplo completo de como implementar um experimento A/B usando a API diretamente:

### 1. Atribuir Variante

```bash theme={null}
curl -X POST https://lfhltqrtfwxoirjmhcdz.supabase.co/functions/v1/variants/assign \
  -H "x-testly-auth: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "experimentId": "homepage-hero-test",
    "userId": "user_123"
  }'
```

**Resposta:**

```json theme={null}
{
  "success": true,
  "data": {
    "variantId": "variant-b",
    "variantName": "Variante B",
    "experimentId": "homepage-hero-test"
  }
}
```

### 2. Registrar Impressão

```bash theme={null}
curl -X POST https://lfhltqrtfwxoirjmhcdz.supabase.co/functions/v1/events/impression \
  -H "x-testly-auth: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "experimentId": "homepage-hero-test",
    "variantId": "variant-b",
    "userId": "user_123"
  }'
```

**Resposta:**

```json theme={null}
{
  "success": true,
  "data": {
    "eventId": "evt_abc123",
    "timestamp": "2024-01-15T10:30:00Z"
  }
}
```

### 3. Registrar Conversão

```bash theme={null}
curl -X POST https://lfhltqrtfwxoirjmhcdz.supabase.co/functions/v1/events/conversion \
  -H "x-testly-auth: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "experimentId": "homepage-hero-test",
    "variantId": "variant-b",
    "userId": "user_123",
    "eventName": "cta_clicked"
  }'
```

**Resposta:**

```json theme={null}
{
  "success": true,
  "data": {
    "eventId": "evt_xyz789",
    "timestamp": "2024-01-15T10:35:00Z"
  }
}
```

***

## SDK vs API Direta

| Aspecto        | SDK React             | API Direta               |
| -------------- | --------------------- | ------------------------ |
| **Setup**      | 2 linhas de código    | Implementação manual     |
| **Cache**      | Automático            | Você precisa implementar |
| **Retry**      | Automático            | Você precisa implementar |
| **TypeScript** | Tipos incluídos       | Você precisa criar       |
| **Impressões** | Automáticas           | Você precisa chamar      |
| **Estado**     | Gerenciado pelo React | Você precisa gerenciar   |
| **Use case**   | Apps React            | Qualquer linguagem       |

***

## Implementação Customizada

Se você quiser criar sua própria camada de abstração (ex: SDK para Vue):

### Exemplo: Cliente JavaScript

```javascript theme={null}
class TestlyClient {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://lfhltqrtfwxoirjmhcdz.supabase.co/functions/v1';
  }

  async assignVariant(experimentId, userId) {
    const response = await fetch(`${this.baseUrl}/variants/assign`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ experimentId, userId })
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    return response.json();
  }

  async recordImpression(experimentId, variantId, userId) {
    const response = await fetch(`${this.baseUrl}/events/impression`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ experimentId, variantId, userId })
    });

    return response.json();
  }

  async recordConversion(experimentId, variantId, userId, eventName) {
    const response = await fetch(`${this.baseUrl}/events/conversion`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ experimentId, variantId, userId, eventName })
    });

    return response.json();
  }
}

// Uso
const client = new TestlyClient('YOUR_API_KEY');

// 1. Atribuir variante
const { data } = await client.assignVariant('homepage-hero', 'user_123');
console.log('Variante:', data.variantId);

// 2. Registrar impressão
await client.recordImpression('homepage-hero', data.variantId, 'user_123');

// 3. Registrar conversão
await client.recordConversion('homepage-hero', data.variantId, 'user_123', 'clicked');
```

***

## Webhooks (Em Desenvolvimento)

Em breve você poderá configurar webhooks para receber notificações de:

* ✅ Experimento atingiu significância estatística
* ✅ Conversões registradas
* ✅ Mudanças em experimentos

<Note>
  Webhooks estão em desenvolvimento. Entre em contato via [suporte@testly.com.br](mailto:suporte@testly.com.br) se precisar dessa funcionalidade.
</Note>

***

## Exemplos em Outras Linguagens

### Python

```python theme={null}
import requests

class TestlyClient:
    def __init__(self, api_key):
        self.api_key = api_key
        self.base_url = 'https://lfhltqrtfwxoirjmhcdz.supabase.co/functions/v1'
        self.headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        }
    
    def assign_variant(self, experiment_id, user_id):
        response = requests.post(
            f'{self.base_url}/variants/assign',
            headers=self.headers,
            json={'experimentId': experiment_id, 'userId': user_id}
        )
        return response.json()

# Uso
client = TestlyClient('YOUR_API_KEY')
result = client.assign_variant('homepage-hero', 'user_123')
print(result['data']['variantId'])
```

### PHP

```php theme={null}
<?php
class TestlyClient {
    private $apiKey;
    private $baseUrl = 'https://lfhltqrtfwxoirjmhcdz.supabase.co/functions/v1';
    
    public function __construct($apiKey) {
        $this->apiKey = $apiKey;
    }
    
    public function assignVariant($experimentId, $userId) {
        $ch = curl_init("{$this->baseUrl}/variants/assign");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "Authorization: Bearer {$this->apiKey}",
            "Content-Type: application/json"
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            'experimentId' => $experimentId,
            'userId' => $userId
        ]));
        
        $response = curl_exec($ch);
        curl_close($ch);
        
        return json_decode($response, true);
    }
}

// Uso
$client = new TestlyClient('YOUR_API_KEY');
$result = $client->assignVariant('homepage-hero', 'user_123');
echo $result['data']['variantId'];
?>
```

***

## Próximos Passos

<CardGroup cols={2}>
  <Card title="Autenticação" icon="key" href="/api-reference/authentication">
    Detalhes sobre API Keys e segurança
  </Card>

  <Card title="Endpoints" icon="code" href="/api-reference/experiments/list">
    Documentação completa de cada endpoint
  </Card>

  <Card title="SDK React" icon="react" href="/sdk/installation">
    Use o SDK oficial para React
  </Card>

  <Card title="Exemplos" icon="book" href="/examples/hero-section">
    Veja implementações práticas
  </Card>
</CardGroup>

***

## Suporte

Precisa de ajuda com a API?

<Card title="Contato" icon="envelope" href="mailto:suporte@testly.com.br">
  **Email**: [suporte@testly.com.br](mailto:suporte@testly.com.br)

  Respondemos em até 24h (geralmente muito mais rápido!)
</Card>
