Documentação da API

Um único endpoint HTTP pra integrar a AIKO em qualquer lugar que fale JSON.

Autenticação

Toda chamada precisa do header Authorization: Bearer aiko_sk_.... Gere uma key em Configurações → Segurança.

POST /v1/chat/completions

Recebe uma lista de mensagens (system/user/assistant) e devolve a resposta da AIKO. Use stream: true pra receber a resposta via Server-Sent Events, no formato chat.completion.chunk, terminando em data: [DONE].

Se o erro acontecer DEPOIS que o streaming já começou (resposta HTTP 200 já enviada), ele chega como um único evento data: {"error": {"message": "...", "type": "api_error", "code": "..."}}, e o stream termina imediatamente — sem o data: [DONE] final.

Códigos de erro

  • invalid_request (400) — schema da requisição inválido.
  • content_too_large (400) — conteúdo total das mensagens acima de 20.000 caracteres.
  • invalid_api_key (401) — API key ausente, inválida ou revogada.
  • rate_limit_exceeded (429) — mais de 20 requisições/minuto por key (100/min por IP sem key).
  • quota_exceeded (429) — cota mensal de tokens do plano esgotada.
  • provider_error (500) — falha ao gerar a resposta.

Exemplos

curl

curl https://api.project-aiko.com/v1/chat/completions \
  -H "Authorization: Bearer aiko_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "Qual é a capital do Brasil?"}]}'

JavaScript

const res = await fetch("https://api.project-aiko.com/v1/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": "Bearer aiko_sk_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    messages: [{ role: "user", content: "Qual é a capital do Brasil?" }],
  }),
});
const data = await res.json();
console.log(data.choices[0].message.content);

Python

import requests

res = requests.post(
    "https://api.project-aiko.com/v1/chat/completions",
    headers={"Authorization": "Bearer aiko_sk_..."},
    json={"messages": [{"role": "user", "content": "Qual é a capital do Brasil?"}]},
)
print(res.json()["choices"][0]["message"]["content"])

Console interativo

Testa a API de verdade com a sua própria key — consome a sua cota real, do mesmo jeito que uma integração em produção consumiria. A key fica só no seu navegador (nunca é enviada pra nenhum lugar além da própria chamada à API).

Webhooks

Configure endpoints em Configurações → Webhooks pra receber estes 5 eventos. Cada entrega é um POST com o corpo { id, event, created, data } e os headers X-AIKO-Event, X-AIKO-Delivery e X-AIKO-Signature.

  • completion.finished
    { "apiKeyId": "...", "inputTokens": 12, "outputTokens": 48, "totalTokens": 60 }
  • completion.failed
    { "apiKeyId": "...", "reason": "provider_error" }
  • usage.threshold_reached
    { "apiKeyId": "...", "threshold": 80, "usedTokens": 40000, "monthlyTokenLimit": 50000 }
  • api_key.created
    { "apiKeyId": "...", "label": "produção" }
  • api_key.revoked
    { "apiKeyId": "...", "label": "produção" }

Verificando a assinatura

X-AIKO-Signature é sha256= seguido do HMAC-SHA256 (hex) do corpo bruto exato recebido, calculado com o segredo do endpoint (visível uma única vez na criação, em Configurações → Webhooks).

const crypto = require("node:crypto");

function isValidSignature(secret, rawBody, header) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  const headerBuf = Buffer.from(header);
  const expectedBuf = Buffer.from(expected);
  if (headerBuf.length !== expectedBuf.length) return false;
  return crypto.timingSafeEqual(headerBuf, expectedBuf);
}