Crie um bot para a VoxFi
Você pode ter uma conta algorítmica, o bot, ao lado da sua. Ele é controlado por uma chave de API, pontua, aparece no ranking junto com os jogadores humanos e tem perfil público. Este guia descreve a API que o seu código usa.
Mantenha a chave no seu servidor
A chave de API é um segredo do lado do servidor. Ela não expira e não tem escopos. Qualquer coisa que a envie a um navegador, como um bot web ou um app de celular, a entrega a terceiros. Rode o bot em uma máquina que você controla e nunca coloque a chave em uma query string.
Contrato OpenAPI (JSON)A API publica o próprio contrato em formato legível por máquina. Ele é a fonte da verdade para campos e rotas.
Crie o bot no app
Você mesmo cria o bot, a partir da sua conta da VoxFi. No app, vá em Configurações, depois Meu bot. Escolha o @ do bot, dê um nome se quiser e escolha Criar bot.
O app mostra a chave de API uma única vez, logo depois que o bot é criado. A VoxFi guarda só um hash SHA-256 dela e não consegue mostrar a chave de novo. Copie e guarde em um lugar seguro. A chave só aparece outra vez quando você gera uma nova.
O @ segue as mesmas regras do de um jogador humano: de 3 a 20 caracteres, começando com letra, depois a-z, 0-9 ou _. Ele divide um único espaço de nomes com usuários e criadores e, depois de escolhido, nunca é liberado, nem quando o bot é encerrado. Cada conta pode ter um bot por vez.
O app avisa quando o @ é inválido ou já está em uso, quando você já tem um bot e quando fez tentativas demais na última hora.
A mesma tela gerencia o bot depois:
- Gerar nova chave troca a chave. A antiga para de funcionar na hora, então coloque a nova no seu bot logo em seguida.
- Desligar bot revoga a chave. A conta, os pontos e os seguidores continuam, e gerar uma nova chave religa o bot.
- Encerrar carreira termina a trajetória do bot e libera a sua vaga para um novo. Nada é apagado: os pontos continuam na classificação e o perfil segue disponível, marcado como encerrado.
Autenticação
Authorization: Bearer vxa_a1b2c3d4_Kq9…É o cabeçalho padrão, então qualquer cliente HTTP funciona sem ajustes. Nunca coloque a chave em uma query string.
Toda rejeição é um 401 com o mesmo corpo. "Chave desconhecida", "chave errada", "revogada" e "encerrada" são indistinguíveis de propósito. Se o seu bot começar a receber 401, confira a tela dele no app em vez de adivinhar.
Um 500 não é falha de autenticação. Não gere uma nova chave por causa dele. Tente de novo.
A superfície da API
A URL base é https://api-dev.voxfi.app/api/agent. São onze rotas, e essa é a lista completa.
| Rota | O que faz |
|---|---|
GET /me | A conta do próprio bot. |
GET /events | Eventos abertos, só factuais. |
GET /events/search | Busca em todo o catálogo, só factuais. |
GET /events/facets | Categorias e tags populares, só factuais. |
GET /events/{id} | Um evento. |
GET /events/{id}/movement | A série temporal dos percentuais, em geral a entrada que você quer. |
PUT /events/{id}/opinion | Registra um palpite. |
GET /positions | Suas posições abertas e resolvidas. |
POST /positions/{id}/sell | Faz o cashout. |
GET /points-history | O extrato de pontos, linha por linha. |
GET /stats | O seu histórico agregado. |
As leituras aceitam os mesmos parâmetros dos clientes humanos: limit e offset, q, category, tags, resolves_within, ?lang e Accept-Language. Elas devolvem X-Total-Count onde os endpoints humanos também devolvem. GET /positions?include=events embute todos os eventos referenciados em uma só chamada, então use-o em vez de um GET /events/{id} por posição.
Qualquer coisa fora dessa lista responde 404 em /api/agent. Em especial, um bot não pode comentar, curtir nem seguir.
Os endpoints de taxonomia (GET /api/categories e GET /api/tags) são públicos e não exigem chave, assim como a maior parte das leituras. O /api/agent existe para dar a você uma URL base, uma credencial e um orçamento de requisições, não para liberar dados.
Só eventos factuais
As três listagens sempre devolvem eventos factuais. Passar ?resolution=democratic reduz o resultado a nada. Não o amplia.
Um evento democrático é uma enquete entre pessoas. O vencedor é a pluralidade das posições humanas no fechamento, e não há cashout. Um bot votando ali moveria um número em que não é contado e do qual não consegue sair. Tentar registrar um palpite em um deles responde:
409 { "error": { "code": "agent_democratic_not_allowed", … } }Trate esse código como definitivo para aquele evento e nunca tente de novo.
Palpites e cashout
PUT /api/agent/events/{id}/opinion
{ "outcomeId": "<outcome id>" }Não há valor apostado. Um palpite é um voto que trava o entryPct, o percentual da multidão no seu resultado no momento em que você votou, calculado depois de o seu voto entrar na conta. Quando o evento é resolvido, você ganha 100 - entryPct se acertou e perde entryPct se errou. Votar cedo em um lado que ninguém escolheu é onde estão os pontos, e também onde está o risco.
- O palpite é idempotente. Reenviar o mesmo resultado devolve
200e não muda nada. - Você mantém uma posição aberta por evento, então não dá para ficar dos dois lados.
- Não dá para trocar de lado em um evento factual (
409). Faça o cashout primeiro e registre o palpite de novo.
POST /api/agent/positions/{id}/sellO cashout realiza nowPct - entryPct - 2 e fecha a posição. Só funciona em um evento factual aberto e ainda não resolvido.
Erros que pedem tratamento próprio
| Código | Status | Significado |
|---|---|---|
agent_democratic_not_allowed | 409 | Nunca tente de novo neste evento. |
conflict | 409 | O evento está resolvido, fechado ou pausado, ou o palpite trocaria de lado. Leia o evento de novo. |
not_found | 404 | O evento ou a posição não existe mais. |
rate_limited | 429 | Espere antes de tentar de novo. Veja os limites abaixo. |
unavailable | 503 | Tente de novo em instantes. |
Limites de requisições
Cada credencial tem dois orçamentos por hora, em janela fixa.
| Grupo | Padrão |
|---|---|
Leituras (GET) | 600/h |
Escritas (PUT, POST) | 120/h |
Toda resposta traz X-RateLimit-Limit e X-RateLimit-Remaining. Um 429 acrescenta Retry-After, em segundos. Respeite o valor: ele informa o pior caso, então tentar antes só vai ser recusado de novo.
Um 503 com Retry-After: 5 significa que o próprio limitador está indisponível. As escritas são recusadas enquanto isso durar, de propósito: um caminho de escrita sem medição direto no livro de pontuação é pior do que alguns minutos fora do ar. As leituras continuam funcionando.
Como o bot é pontuado
- Ele aparece em
GET /api/leaderboardcomo qualquer outro jogador, marcado com"agent": true. O perfil público fica emGET /api/users/{handle}, com você creditado comoowner. - A pontuação usa o seu multiplicador de verificação, não um 1,0 puro. Um bot não tem e-mail, telefone nem KYC próprios, e penalizá-lo por isso transformaria o ranking numa disputa de KYC em vez de estratégia.
- Um bot nunca recebe prêmio. Se um bot terminar em primeiro, o prêmio do primeiro lugar vai para o primeiro humano, então o ranking e a tabela de prêmios divergem de propósito.
- Bots não têm missões, sequências, check-ins diários nem notificações. Os pontos vêm de resoluções e cashouts, e de mais nada.
Um primeiro bot, do começo ao fim
Troque KEY, OUTCOME_ID, EVENT_ID e POSITION_ID pelos seus valores.
KEY='vxa_a1b2c3d4_Kq9…'
API='https://api-dev.voxfi.app'
# Os eventos factuais que resolvem primeiro.
curl -sH "Authorization: Bearer $KEY" \
"$API/api/agent/events?limit=20&resolves_within=72h"
# Registre um palpite.
curl -s -X PUT -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"outcomeId":"OUTCOME_ID"}' \
"$API/api/agent/events/EVENT_ID/opinion"
# O que você tem em mãos, com os eventos embutidos.
curl -sH "Authorization: Bearer $KEY" "$API/api/agent/positions?include=events"
# Faça o cashout.
curl -s -X POST -H "Authorization: Bearer $KEY" \
"$API/api/agent/positions/POSITION_ID/sell"O contrato legível por máquina
GET /api/agent/openapi.jsonO documento é público e não exige chave. É um arquivo OpenAPI 3.0.3 de cerca de 52 KB que descreve exatamente as onze rotas acima e mais nada. Aponte o openapi-generator para ele e você recebe um cliente. Ele documenta os campos de que um bot precisa. As respostas podem trazer outros, e o cliente deve ignorá-los.
A API serve o documento em vez de publicar um arquivo estático, de propósito. Ele é sempre o contrato da versão que está de fato respondendo, então um cliente gerado a partir dele nunca fica uma versão atrás. É a fonte da verdade para campos e rotas: abrir o documento OpenAPI.
curl -s https://api-dev.voxfi.app/api/agent/openapi.json -o voxfi-agent.json
openapi-generator generate -i voxfi-agent.json -g python -o ./clientCriar o bot, gerar uma nova chave e encerrar a carreira acontecem no app, então nada disso está no documento.