Novo Cadastre-se grátis, 10 chamadas por nossa conta. Até US$ 1, sem cartão.

API de cobrança

Traga o uso e o custo do seu próprio workspace para os seus próprios sistemas, sem abrir o console. Uma chave de cobrança é uma somente leitura credencial restrita a um único workspace - ela só pode ler dados de cobrança, nada mais.

⚠

Uma chave de cobrança pode ler cada requisição registrada em seu workspace, incluindo chaves que desde então foram excluídas ou revogadas, mas não pode chamar nenhum modelo, nem criar, modificar ou excluir nenhuma chave de API. Usá-la em qualquer outro lugar retorna 401 wrong_key_kind.

Criar uma chave de cobrança

  1. Abra Console → Chaves da API de cobrança (somente proprietário do workspace). Dê um nome a ela, opcionalmente restrinja-a a uma lista de permissões de IP ou defina uma expiração e, em seguida, copie a chave - ela começa com sk-syn-bill- e é exibida apenas uma vez.
  2. Chame os endpoints abaixo usando-a como token Bearer. Revogue-a a qualquer momento na mesma página - revogar a invalida imediatamente e não afeta mais nada no workspace.
  3. Uma chave está vinculada a quem a criou: se essa pessoa deixar de ser o proprietário do workspace, ela para de funcionar e retorna 403 key_owner_not_authorized.

Autenticação

Cada chamada precisa de Authorization: Bearer sk-syn-bill-... contra a URL base abaixo. Uma chave de cobrança só funciona nesses endpoints, e esses endpoints só aceitam uma chave de cobrança - qualquer outra combinação retorna 401 wrong_key_kind.

Authorization: Bearer sk-syn-bill-...

URL base: https://synthorai.io/api/v1/billing

ℹ

O escopo é todo o workspace: cada chave de inferência nele contida, incluindo as excluídas - suas linhas históricas continuam consultáveis. api_key_id e model só podem restringir o resultado, nunca ampliá-lo; cada consulta fica ancorada no próprio workspace da chave.

ℹ

Cada consulta é executada na réplica de leitura, nunca na primária. Um processo sem réplica configurada responde 503 replica_unavailable em vez de recorrer a ela silenciosamente.

✓

Campos de tokens: seguem a convenção da OpenAI - prompt_tokens é o total de tokens de entrada e já inclui cada leitura e escrita de cache abaixo, e completion_tokens já inclui reasoning_tokens. Nenhum dos dois é somado aos totais - são um detalhamento, não tokens extras.

A parte de leitura de cache de prompt_tokens é cached_tokens; a parte de escrita de cache é cache_write_tokens, dividida ainda nas linhas de /records em cache_write_5m_tokens e cache_write_1h_tokens conforme o TTL.

✓

Campos monetários: cost_usd é o valor efetivamente cobrado. byok_list_price_usd é o que uma requisição BYOK teria custado ao preço de tabela - 0 para uma requisição não BYOK. Não existe list_price_usd em nenhum lugar desta API.

ℹ

Aqui "erro" significa qualquer requisição que chegou à API e foi rejeitada - um 4xx como 402 (saldo insuficiente), 403 ou 429, bem como uma falha upstream. Só ficam de fora as rejeições da nossa própria infraestrutura interna, exatamente como no console. Rejeições são registradas no máximo uma vez por chave, código de status e minuto em cada servidor, então as contagens de 402, 403 e 429 são um mínimo; requisições bem-sucedidas e cobranças estão completas.

GET /usage - uso agregado

GET /usage

Linhas pré-agregadas por hora ou por dia, feitas para faturamento e painéis. Vêm do agregado horário somado às requisições gravadas desde a última ingestão, então os buckets recentes não ficam um ciclo de ingestão inteiro atrasados.

ParâmetroTipoDescrição
start*stringInício do intervalo: um timestamp RFC 3339 ou uma data como 2026-09-01.
endstringFim do intervalo. Padrão: agora.
granularitystringTamanho do bucket: hour ou day. Padrão: day.
group_bystringDimensões para desagregar as linhas: api_key, model, ou ambos (qualquer subconjunto). Padrão: ambos.
api_key_idintegerFiltra por um ou mais ids de chave de API. Repetível; apenas restringe, nunca amplia.
modelstringFiltra por um ou mais ids de modelo. Repetível.
limitintegerLinhas por página. Padrão 1000, limitado a 5000.
cursorstringCursor de paginação opaco, obtido do meta.next_cursor da página anterior.

Em cada linha, api_key_id e api_key_name só aparecem quando group_by inclui api_key, e model somente quando inclui model. avg_latency_ms pode ser null quando um bucket não tem amostras de latência.

Exemplo de requisição

curl "https://synthorai.io/api/v1/billing/usage?start=2026-09-01&end=2026-09-24&granularity=day" \
  -H "Authorization: Bearer sk-syn-bill-..."

Exemplo de resposta

{
  "data": [
    {
      "bucket_start": "2026-09-23T00:00:00Z",
      "bucket_end": "2026-09-24T00:00:00Z",
      "api_key_id": 42,
      "api_key_name": "prod-backend",
      "model": "claude-sonnet-5",
      "requests": 1280,
      "success_requests": 1265,
      "error_requests": 15,
      "errors_4xx": 12,
      "errors_429": 2,
      "errors_5xx": 1,
      "prompt_tokens": 512000,
      "completion_tokens": 98000,
      "cached_tokens": 210000,
      "cache_write_tokens": 8000,
      "reasoning_tokens": 4000,
      "cost_usd": 4.1732,
      "byok_list_price_usd": 0,
      "byok_requests": 0,
      "avg_latency_ms": 812,
      "final": true
    }
  ],
  "meta": {
    "generated_at": "2026-09-24T08:00:00Z",
    "data_complete_until": "2026-09-24T06:00:00Z",
    "timezone": "UTC",
    "currency": "USD",
    "next_cursor": null,
    "has_more": false
  }
}

GET /records - linhas por requisição

GET /records

Uma linha por requisição, pensada para a sincronização incremental no seu próprio banco de dados. Sincronize por cursor, nunca por tempo, e remova duplicatas das linhas recebidas por record_id - veja "Evitando lacunas de tempo" abaixo para saber por quê.

ParâmetroTipoDescrição
cursorstringCursor de sincronização opaco (string), obtido do meta.next_cursor da chamada anterior. Informe exatamente um entre cursor ou start; ele não tem limite de intervalo.
startstringInício do intervalo (timestamp RFC 3339 ou data). Informe exatamente um entre cursor ou start; um intervalo start/end é limitado a 31 dias, enquanto cursor não tem limite de intervalo.
endstringFim do intervalo. Padrão: agora.
api_key_idintegerFiltra por um ou mais ids de chave de API. Repetível; apenas restringe, nunca amplia.
modelstringFiltra por um ou mais ids de modelo. Repetível.
limitintegerLinhas por página. Padrão 500, limitado a 1000.

Exemplo de requisição

curl "https://synthorai.io/api/v1/billing/records?start=2026-09-24T00:00:00Z&limit=500" \
  -H "Authorization: Bearer sk-syn-bill-..."

Exemplo de resposta

{
  "data": [
    {
      "record_id": "rec_8f2a91c4",
      "request_id": "req_9f3c2b1a",
      "recorded_at": "2026-09-24T05:58:31Z",
      "completed_at": "2026-09-24T05:58:29Z",
      "api_key_id": 42,
      "api_key_name": "prod-backend",
      "model": "claude-sonnet-5",
      "status": "success",
      "status_code": 200,
      "prompt_tokens": 812,
      "completion_tokens": 194,
      "cached_tokens": 512,
      "cache_write_tokens": 64,
      "cache_write_5m_tokens": 64,
      "cache_write_1h_tokens": 0,
      "cost_usd": 0.00412,
      "byok_list_price_usd": 0,
      "is_byok": false,
      "is_stream": true,
      "duration_ms": 1340,
      "ttft_ms": 210
    }
  ],
  "meta": {
    "next_cursor": "eyJvIjoiODgxNDA5MCJ9",
    "has_more": false,
    "window_final": true,
    "safe_until": "2026-09-24T05:58:31Z",
    "latest_recorded_at": "2026-09-24T05:58:31Z",
    "data_complete_until": "2026-09-24T05:58:00Z"
  }
}
ParâmetroDescrição
next_cursorCursor para a próxima chamada. Sempre presente.
has_moreIndica se chamar novamente agora com este cursor retornaria mais linhas.
window_finaltrue somente se você informou um end e ele é anterior ou igual a safe_until - nesse caso o intervalo solicitado está garantido como completo. Ausente ou false caso contrário.
safe_untilO recorded_at mais recente que um chamador pode considerar definitivo; linhas mais recentes do que isso ainda estão sendo retidas.
latest_recorded_atO recorded_at mais recente entre todas as linhas, definitivas ou não.
data_complete_untilO mesmo valor que /freshness retorna - até onde o rollup por hora está completo, para conferência cruzada com /usage.
⚠

Base temporal: /usage agrupa por completed_at (quando a requisição terminou). O filtro start/end de /records se baseia em recorded_at (quando a linha foi escrita, o que pode ficar atrás da conclusão sob carga). Para reconciliar /records com /usage, agrupe você mesmo as linhas sincronizadas por completed_at, não por recorded_at.

GET /records/export - exportação em streaming

GET /records/export

Os mesmos filtros de /records, transmitidos como JSON delimitado por novas linhas (application/x-ndjson) - feito para um grande backfill em vez de uma lista paginada. Apenas uma exportação pode ser transmitida por workspace por vez; uma segunda recebe 429 too_many_concurrent_requests.

Exemplo de requisição

curl -N "https://synthorai.io/api/v1/billing/records/export?cursor=eyJvIjoiODgxNDAzMiJ9" \
  -H "Authorization: Bearer sk-syn-bill-..."

Exemplo de resposta

{"record_id":"rec_8f2a91c4","request_id":"req_9f3c2b1a","model":"claude-sonnet-5","status":"success","cost_usd":0.00412}
{"record_id":"rec_8f2a91c5","request_id":"req_9f3c2b1b","model":"claude-sonnet-5","status":"success","cost_usd":0.00398}
{"_meta":{"next_cursor":"eyJvIjoiODgxNDA5MSJ9","rows":2,"complete":true,"window_final":true,"generated_at":"2026-09-24T06:00:02Z"}}

A última linha do stream é um _meta objeto:

ParâmetroDescrição
next_cursorCursor para a próxima chamada de exportação.
rowsNúmero de registros escritos neste stream.
completefalse significa que o stream parou antes de esgotar o intervalo - retome com cursor=next_cursor.
window_finalMesmo significado de /records: true somente se o end da exportação é anterior ou igual a safe_until.
generated_atMomento em que esta linha foi escrita.
stopped_becausePresente quando complete é false: row_cap, scan_cap (o fluxo percorreu sua faixa máxima de id sem encher - comum com filtro estreito), time_cap, query_error ou window_not_final.

GET /summary - estatísticas preliminares e anomalias

GET /summary

Totais, os principais modelos e chaves por custo, e uma taxa de erro para o intervalo, além de uma anomalies lista (high_error_rate, rate_limited, data_not_final, rollup_delayed), cada uma com uma gravidade info ou warning e uma mensagem legível. Os números de um intervalo não finalizado ainda podem mudar - veja abaixo.

ParâmetroTipoDescrição
startstringInício do intervalo. Padrão: 30 dias antes de end.
endstringFim do intervalo. Padrão: agora.
api_key_idintegerFiltra por um ou mais ids de chave de API. Repetível; apenas restringe, nunca amplia.
modelstringFiltra por um ou mais ids de modelo. Repetível.

models_count e keys_count fornecem os totais por trás de top_models e top_keys, que listam no máximo os 20 principais por custo. O intervalo padrão são os 30 dias antes de end quando start é omitido.

Exemplo de requisição

curl "https://synthorai.io/api/v1/billing/summary?start=2026-09-17&end=2026-09-24" \
  -H "Authorization: Bearer sk-syn-bill-..."

Exemplo de resposta

{
  "data": {
    "totals": { "requests": 48210, "cost_usd": 132.55, "error_rate": 0.021 },
    "models_count": 6,
    "keys_count": 3,
    "top_models": [ { "model": "claude-sonnet-5", "cost_usd": 88.10, "byok_list_price_usd": 0 } ],
    "top_keys": [ { "api_key_id": 42, "api_key_name": "prod-backend", "cost_usd": 61.30, "byok_list_price_usd": 0 } ],
    "anomalies": [
      { "type": "data_not_final", "severity": "info", "message": "The last 2 hours of this range are not yet final." }
    ]
  },
  "meta": {
    "generated_at": "2026-09-24T06:00:02Z",
    "data_complete_until": "2026-09-24T04:00:00Z"
  }
}

GET /freshness - grau de integridade dos dados

GET /freshness

Retorna data_complete_until, latest_recorded_at, safe_until e pipeline_lag_seconds - consulte-o antes de tratar um intervalo recém-obtido como definitivo. safe_until é o recorded_at mais recente que um chamador pode considerar completo; linhas mais recentes ainda podem estar chegando.

Exemplo de requisição

curl "https://synthorai.io/api/v1/billing/freshness" \
  -H "Authorization: Bearer sk-syn-bill-..."

Exemplo de resposta

{
  "data": {
    "data_complete_until": "2026-09-24T04:00:00Z",
    "latest_recorded_at": "2026-09-24T05:58:31Z",
    "safe_until": "2026-09-24T05:58:31Z",
    "pipeline_lag_seconds": 47
  },
  "meta": { "generated_at": "2026-09-24T06:00:02Z" }
}

GET /balance - o que o workspace pode gastar agora

GET /balance

Retorna o saldo disponível atual do workspace, o mesmo valor exibido no console. Feito para consultas periódicas: a cada 30 a 60 segundos é suficiente. Tem um limite de taxa próprio, então consultá-lo não consome o orçamento dos endpoints de dados, e ele responde mesmo com saldo zero.

Exemplo de requisição

curl "https://synthorai.io/api/v1/billing/balance" \
  -H "Authorization: Bearer sk-syn-bill-..."

Exemplo de resposta

{
  "data": {
    "available_usd": 1284.37,
    "debt_usd": 0,
    "source": "live",
    "voucher": null,
    "scheduled_credits": [
      { "amount_usd": 250, "release_at": "2026-10-01T00:00:00Z" }
    ],
    "scheduled_credit_total_usd": 250
  },
  "meta": { "generated_at": "2026-09-24T06:00:02Z", "currency": "USD" }
}
ParâmetroDescrição
available_usdO saldo geral contra o qual as requisições são cobradas agora. Nunca abaixo de 0. Pode subir brevemente quando requisições em andamento são liquidadas; para gastos, use /usage ou /records.
debt_usdO saldo devedor: o consumo acima do valor creditado. 0 quando não há nada devido. Uma recarga o quita primeiro; só o restante vai para available_usd.
sourcelive: lido do registro em tempo real. delayed: o registro não pôde ser acessado e o valor vem de uma cópia no banco de dados que pode estar até cerca de 30 segundos atrasada.
voucherCrédito promocional apenas para geração de imagens (applies_to), nos padrões de modelo listados e até expires_at; as demais requisições usam só available_usd, e este crédito não faz parte dele. null quando não há; active é false depois de expirado.
scheduled_creditsCréditos já acordados que chegam em parcelas (amount_usd, release_at); cada parcela é somada ao saldo em até cerca de 10 minutos após release_at, não antes. scheduled_credit_total_usd é a soma delas.

Erros

Cada erro é {"error": {"type", "message", "hint"}}:

{
  "error": {
    "type": "range_too_large",
    "message": "the requested range exceeds this endpoint's cap",
    "hint": "narrow start/end to at most 31 days, or sync /records with a cursor instead"
  }
}
TipoStatus HTTPSignificado
invalid_parameter400Um parâmetro de consulta está ausente, malformado ou fora do intervalo.
range_too_large400O intervalo de tempo ou a janela de id solicitados são maiores do que o endpoint permite; o hint informa o limite correspondente.
start_too_recent400Uma janela start/end começa depois de safe_until, onde seu limite inicial ainda não está estável. Tente de novo após o tempo do cabeçalho Retry-After ou sincronize com um cursor.
wrong_key_kind401A credencial não é uma chave de cobrança, ou uma chave de cobrança foi usada fora desses endpoints.
authentication_error401A chave está ausente, é inválida, expirou, ou está bloqueada pela sua lista de permissões de IP.
key_owner_not_authorized403O criador desta chave não é mais o proprietário do workspace. Chaves de cobrança são exclusivas do proprietário e deixam de funcionar no momento em que a propriedade muda de mãos; o novo proprietário precisa criar a sua própria.
rate_limited429Mais de 60 requisições por minuto neste workspace. Tente novamente depois do tempo indicado no cabeçalho Retry-After.
too_many_concurrent_requests429Mais de 3 requisições simultâneas neste workspace, ou outra exportação já em andamento.
replica_unavailable503Este processo não tem nenhuma réplica de leitura configurada; a API nunca recorre à primária.
query_timeout503A consulta excedeu o tempo limite de 10 segundos ou o prazo de 15 segundos. Restrinja o intervalo e tente novamente.
internal_error500Um erro inesperado do servidor. Tente novamente e reporte se persistir.

Limites de taxa e limites máximos

ProteçãoValor
Limite de taxa60 requisições por minuto por workspace, uma janela deslizante compartilhada entre todas as instâncias.
Concorrência3 requisições simultâneas por workspace em cada servidor, e um fluxo de exportação por workspace em cada servidor.
Consulta do saldo/balance: 60 requisições por minuto e 2 simultâneas por workspace, contadas separadamente dos outros endpoints.
Limites de intervalo/usage: 31 dias com granularidade hour, 366 dias com day. /summary: até 366 dias. /records e a exportação: até 31 dias.
Limites de página/usage retorna até 5.000 linhas por página, /records até 1.000. A exportação transmite páginas de 2.000 e para em 1.000.000 de linhas - retomável com cursor. Também para depois de percorrer 2.000.000 de ids de registro (stopped_because=scan_cap) e ajusta o ritmo ao banco de dados; retome com cursor.
CacheCada resposta traz Cache-Control: no-store.

Nunca é retornado: channel_id, upstream_request_id, usage_raw, other, content, ip_address, user_agent, cost_detail.

Evitando lacunas de tempo

As requisições são gravadas no log de forma assíncrona após terminarem (normalmente segundos, mais tempo em caso de acúmulo), e o rollup por hora que /usage e /summary leem é ingerido em lotes. As horas mais recentes estão sempre um pouco incompletas. /usage e /summary também somam as requisições gravadas desde a última ingestão (meta.live_tail é true); se o agregado estiver atrasado demais para isso, meta.live_tail é false e os buckets recentes ficam parciais.

data_complete_until é o mais antigo entre estes dois pontos: a marca d'água do rollup por hora menos seu atraso de pipeline atual, ou a requisição mais antiga ainda não incorporada ao rollup - menos uma margem de segurança de 30 minutos, arredondada para baixo até a hora.

ℹ

Um bucket final é estável, com uma exceção: o job de reconciliação diária ainda pode corrigir uma hora dentro de 48 horas se encontrar um desvio. /records é sempre a fonte da verdade para os números exatos de uma requisição.

Cada linha de /usage carrega um indicador final : true , válido assim que seu bucket termina antes ou em data_complete_until (valor de /freshness). Um bucket final nunca muda novamente.

  • Agregados: faça upsert de cada linha no seu próprio armazenamento por (bucket_start, api_key_id, model), e busque novamente qualquer bucket enquanto ele ainda for final: false. Nunca calcule um delta subtraindo um total antigo de um novo.
  • Linhas brutas: sincronize por cursor, nunca por tempo. Guarde o next_cursor e retome a partir dele na próxima chamada, e remova duplicatas das linhas recebidas por record_id (um id opaco estável por linha) para o caso de uma página reenviada entregar a mesma linha de novo. Linhas com menos de cerca de 5 minutos são retidas - safe_until é o horário da linha mais recentemente registrada menos 5 minutos - de modo que uma linha ainda sendo confirmada nunca escape para antes de uma posição de cursor já entregue, e nada cai em uma lacuna. Para contar requisições, conte os request_id distintos.
  • Janela delimitada: se você consultar um intervalo start/end em vez de sincronizar por cursor, confie que ele está completo somente quando window_final for true (só é true quando você informou um end e ele é anterior ou igual a safe_until). Se window_final for false, chame novamente depois com o mesmo intervalo, ou passe a sincronizar por cursor. Uma janela deve começar no máximo em safe_until; um início posterior retorna 400 start_too_recent com um cabeçalho Retry-After.

Integração recomendada

  • Faturamento noturno: chame /usage uma vez por dia com granularity=day, e busque novamente qualquer bucket que sua última execução ainda via como final: false.
  • Detalhe por requisição: chame /records a cada hora com cursor definido para o último next_cursor que você armazenou, continue paginando enquanto has_more for true, e remova duplicatas das linhas recebidas por record_id.
  • Painéis: chame /summary para o intervalo visível em vez de agregar /records você mesmo - ele já traz a lista de anomalias.

Precisa gerar ou gerenciar chaves de API normais de forma programática em vez de ler dados de cobrança? Consulte Chaves de provisioning.