> ## 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.

# Integrações

> Conecte área de membros, emissor de nota e rastreador de campanha, vincule um canal do Telegram ou um servidor do Discord e faça a venda aprovada liberar o acesso sozinha.

Doze operações para a pergunta que aparece logo depois da primeira venda: **como o comprador entra na área de membros sem eu mandar nada à mão?**

São duas famílias, e elas se conectam de jeitos diferentes:

| Família                    | Providers                                                                                      | Como conecta                   |
| -------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------ |
| Aplicativos com credencial | `memberkit`, `cademi`, `spedy`, `notazz`, `reportana`, `utmify`, `metrito`, `voxuy`, `astrofy` | Você envia a chave do provedor |
| Canais de comunidade       | `telegram`, `discord`                                                                          | O bot gera um código lá dentro |

O `provider` vai no caminho, e o enum é validado. Um nome que não existe responde `422` com a lista inteira:

```json theme={null}
{
  "success": false,
  "message": "provider: Invalid enum value. Expected 'memberkit' | 'cademi' | 'spedy' | 'notazz' | 'reportana' | 'utmify' | 'metrito' | 'voxuy' | 'astrofy' | 'telegram' | 'discord', received 'hotmart'"
}
```

## 1. Veja o que já está conectado

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

```json theme={null}
{
  "success": true,
  "data": [],
  "pagination": { "page": 1, "pageSize": 5, "total": 0, "totalPages": 0 }
}
```

Lista vazia significa que aquele aplicativo nunca foi conectado nesta empresa. Com conexões, cada item traz o apelido, o recorte de produtos e — o campo que interessa ao diagnóstico — `hasCredentials`:

```json theme={null}
{
  "success": true,
  "data": [
    {
      "id": "clx9m4t7p0001qz0a5r3d8k2v",
      "provider": "memberkit",
      "name": "MemberKit — área principal",
      "active": true,
      "status": null,
      "externalId": null,
      "hasCredentials": true,
      "productIds": ["clx8a2h4k0001qz0a1b2c3d4e"],
      "createdAt": "2026-08-02T14:21:00.000Z",
      "updatedAt": "2026-09-01T09:35:00.000Z"
    }
  ],
  "pagination": { "page": 1, "pageSize": 5, "total": 1, "totalPages": 1 }
}
```

<Note>
  A credencial guardada **nunca volta** por esta API. O que sai é `hasCredentials: true` — suficiente para saber que a conexão está completa, inútil para quem quiser roubar a chave.
</Note>

## 2. Conecte um aplicativo com credencial

Cada provedor pede um conjunto próprio de campos, e a Ephra valida a credencial junto ao provedor na hora: uma chave recusada não vira conexão.

| Provider    | Campos obrigatórios         |
| ----------- | --------------------------- |
| `memberkit` | `apiKey`                    |
| `spedy`     | `apiKey`                    |
| `utmify`    | `apiKey`                    |
| `metrito`   | `apiKey` (connection key)   |
| `cademi`    | `apiKey` + `subdomain`      |
| `reportana` | `clientId` + `clientSecret` |

```bash theme={null}
curl -s -X POST https://api.ephra.io/v1/integrations/cademi \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Cademi — turma 2026",
    "apiKey": "cdm_live_8f2a41c9d7b34e51",
    "subdomain": "doceoficio",
    "active": true,
    "productIds": ["cmty05wl0000apyg1bx1566ej"]
  }'
```

```json theme={null}
{
  "success": true,
  "data": {
    "id": "clx9m4t7p0001qz0a5r3d8k2v",
    "provider": "cademi",
    "name": "Cademi — turma 2026",
    "active": true,
    "status": null,
    "externalId": null,
    "hasCredentials": true,
    "productIds": ["cmty05wl0000apyg1bx1566ej"],
    "createdAt": "2026-08-02T14:21:00.000Z",
    "updatedAt": "2026-09-01T09:35:00.000Z"
  }
}
```

`productIds` recorta o que aquela conexão acompanha. Um produto de outra empresa responde `400` — o mesmo `404` disfarçado que o resto da API usa para não confirmar a existência de ids alheios.

Trocar a credencial depois não exige desconectar e reconectar:

```bash theme={null}
curl -s -X PUT https://api.ephra.io/v1/integrations/cademi/clx9m4t7p0001qz0a5r3d8k2v \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "apiKey": "cdm_live_5e91b7d20c4a63f8" }'
```

Os campos omitidos ficam como estão.

## 3. Vincule o canal da comunidade

Telegram e Discord não entram pela rota de credencial: o bot da Ephra gera um código dentro do canal, e você troca esse código por uma conexão.

<Warning>
  O bot precisa estar no canal **como administrador**, com permissão de convidar e remover membros. Sem isso a vinculação responde `400` — e, pior, uma vinculação que deu certo antes de o bot perder a permissão só falha na hora da entrega, com o comprador olhando.
</Warning>

```bash theme={null}
curl -s -X POST https://api.ephra.io/v1/integrations/telegram/channels \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "code": "TG-7K4M-92XB" }'
```

```json theme={null}
{
  "success": true,
  "data": {
    "id": "clx9z8y7x0001qz0a2f5g6h7j",
    "provider": "telegram",
    "name": "Comunidade Confeitaria Artesanal",
    "active": true,
    "status": "active",
    "externalId": "-1002345678901",
    "hasCredentials": false,
    "productIds": [],
    "createdAt": "2026-08-19T13:40:00.000Z",
    "updatedAt": "2026-09-10T08:05:00.000Z"
  }
}
```

O código vale **uma vez** e expira. Um código errado, já usado ou vencido responde:

```json theme={null}
{ "success": false, "message": "Código de vinculação não encontrado" }
```

Peça um novo ao bot em vez de repetir o mesmo.

## 4. No Discord, descubra o cargo

Entregar acesso no Discord é dar um **cargo** ao comprador. A lista sai do próprio Discord, em tempo real:

```bash theme={null}
curl -s "https://api.ephra.io/v1/integrations/discord/guilds/1287654321098765430/roles?page=1&pageSize=10" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "success": true,
  "data": [
    { "id": "1287654321098765432", "name": "Alunos", "position": 4 },
    { "id": "1287654321098765433", "name": "Mentoria", "position": 3 }
  ],
  "pagination": { "page": 1, "pageSize": 10, "total": 2, "totalPages": 1 }
}
```

O `guildId` é o `externalId` que voltou na vinculação. Guarde o `id` do cargo: é o `roleId` do passo 6.

## 5. Na Memberkit, descubra a turma

Na Memberkit a entrega não é um cargo: é a **turma** em que o comprador é matriculado. O id dela não existe do lado da Ephra — sai da própria Memberkit, consultada na hora:

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

```json theme={null}
{
  "success": true,
  "data": [
    { "id": 48213, "name": "Turma Confeitaria Artesanal — Janeiro" },
    { "id": 48214, "name": "Turma Confeitaria Artesanal — Julho" }
  ],
  "pagination": { "page": 1, "pageSize": 10, "total": 2, "totalPages": 1 }
}
```

O `integrationId` do caminho é o `id` da **conexão**, aquele que saiu de `GET /v1/integrations/memberkit` — não é o id da sua conta na Memberkit. Conexão que não existe, que foi desconectada ou que é de outra empresa responde o `404` de sempre, sem dizer qual dos três casos é:

```json theme={null}
{ "success": false, "message": "Recurso não encontrado" }
```

Guarde o `id` numérico da turma: é o `externalId` do próximo passo.

<Note>
  Esta rota conversa com a Memberkit a cada chamada e herda os problemas de lá. Chave recusada responde `400` — `"A chave de API da MemberKit foi recusada. Reconecte a integração com uma chave válida."` —, e aí o conserto é `PUT /v1/integrations/memberkit/{integrationId}` com a chave nova. Memberkit fora do ar responde `503`: repita em alguns instantes, em vez de tratar como conexão quebrada.
</Note>

## 6. Amarre o produto ao canal

Este é o passo que liga a venda à entrega. Sem ele, o canal está conectado e ninguém entra.

```bash theme={null}
curl -s -X POST https://api.ephra.io/v1/integrations/discord/channels/clx9z8y7x0001qz0a2f5g6h7j/products \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "cmty05wl0000apyg1bx1566ej",
    "roleId": "1287654321098765432"
  }'
```

```json theme={null}
{
  "success": true,
  "data": {
    "id": "clxa1b2c30001qz0a7h4k9m3n",
    "channelId": "clx9z8y7x0001qz0a2f5g6h7j",
    "productId": "cmty05wl0000apyg1bx1566ej",
    "productName": "Curso de Confeitaria Artesanal",
    "roleId": "1287654321098765432",
    "roleName": "Alunos",
    "externalId": null,
    "createdAt": "2026-09-04T18:12:00.000Z"
  }
}
```

`roleId` só faz sentido no Discord — e o `provider` do caminho aqui aceita quatro valores, não dois:

```json theme={null}
{ "success": false, "message": "provider: Invalid enum value. Expected 'telegram' | 'discord' | 'cademi' | 'memberkit', received 'spedy'" }
```

No Telegram o convite é o próprio acesso, e nada mais é preciso. Na `cademi` e na `memberkit` o destino é uma turma, e ela vai em `externalId`: o id do produto na Cademi, o id numérico da turma na Memberkit — o que a seção anterior foi buscar.

```bash theme={null}
curl -s -X POST https://api.ephra.io/v1/integrations/memberkit/channels/clx9m4t7p0001qz0a5r3d8k2v/products \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "cmty05wl0000apyg1bx1566ej",
    "externalId": "48213"
  }'
```

Confira a entrega de um lançamento antes de abrir o carrinho:

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

E desfaça o vínculo quando a turma fechar:

```bash theme={null}
curl -s -X DELETE \
  https://api.ephra.io/v1/integrations/discord/channels/clx9z8y7x0001qz0a2f5g6h7j/products/clxa1b2c30001qz0a7h4k9m3n \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{ "success": true, "data": { "id": "clxa1b2c30001qz0a7h4k9m3n", "deleted": true } }
```

<Note>
  Desvincular vale para as **próximas** vendas. Quem já comprou continua dentro do canal — isto não expulsa ninguém.
</Note>

## 7. Antes da campanha, revalide

O bot pode ter sido removido do canal, ou perdido uma permissão, sem avisar ninguém. Esta chamada reconsulta o provedor para cada canal vinculado e grava o que encontrou:

```bash theme={null}
curl -s -X POST https://api.ephra.io/v1/integrations/discord/channels/refresh \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
```

```json theme={null}
{
  "success": true,
  "data": [],
  "pagination": { "page": 1, "pageSize": 1, "total": 0, "totalPages": 0 }
}
```

Com canais vinculados, cada item volta com o `status` atualizado. É a chamada para rodar na véspera de um lançamento — e a resposta vazia acima é a de uma empresa que ainda não vinculou nenhum servidor.

## 8. Pause sem perder a configuração

`spedy`, `notazz` e `metrito` podem ser pausados: a credencial fica guardada, o envio de dados para.

```bash theme={null}
curl -s -X PATCH https://api.ephra.io/v1/integrations/metrito/184/active \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "active": false }'
```

```json theme={null}
{
  "success": true,
  "data": {
    "id": "184",
    "provider": "metrito",
    "name": "Metrito — loja principal",
    "active": false,
    "status": null,
    "externalId": null,
    "hasCredentials": true,
    "productIds": [],
    "createdAt": "2026-08-02T14:21:00.000Z",
    "updatedAt": "2026-09-01T09:35:00.000Z"
  }
}
```

Para cortar de vez — apagando a credencial guardada e, em `telegram` e `discord`, desfazendo o vínculo do canal:

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

```json theme={null}
{ "success": true, "data": { "id": "184", "deleted": true } }
```

O que já foi entregue continua entregue: desconectar não recolhe acesso de ninguém.

## Todas as operações do domínio

<CardGroup cols={2}>
  <Card title="Conexões" icon="plug" href="/api-reference/plataforma/listar-integrações-de-um-aplicativo">
    Listar, conectar, atualizar, pausar e desconectar aplicativos.
  </Card>

  <Card title="Canais de comunidade" icon="comments" href="/api-reference/plataforma/vincular-canal-de-comunidade">
    Vincular Telegram e Discord e revalidar o status.
  </Card>

  <Card title="Entrega automática" icon="graduation-cap" href="/api-reference/plataforma/vincular-produto-ao-canal">
    Amarrar produto a canal, listar e desfazer.
  </Card>

  <Card title="Cargos do Discord" icon="discord" href="/api-reference/plataforma/listar-cargos-do-servidor-discord">
    Escolher qual cargo o comprador recebe.
  </Card>

  <Card title="Turmas da Memberkit" icon="graduation-cap" href="/api-reference/plataforma/listar-turmas-da-memberkit">
    Descobrir em qual turma a compra matricula o aluno.
  </Card>
</CardGroup>
