Nesta página
- Visão geral
- Primeiros passos
- Automatizar com um agente
- Autenticação
- Tokens e preços
- API de painel SMM
- services
- add
- status
- balance
- cancel
- API da plataforma
- Catálogo
- Conta
- Dois fatores e login
- Preferências e avisos
- Campanhas
- Criar um pedido
- Editar um pedido
- Registros e análises
- Perfis de voto e proxy
- Tokens do Discord
- Cobrança e pagamentos
- Carrinho salvo
- Superfícies internas
- Formatos de resposta
- Objeto site
- Objeto campanha
- Estado da campanha
- Progresso e reembolsos
- Exemplo de ponta a ponta
- Erros
- Limites de requisições
- Limites e observações
Visão geral
A Toplistbot expõe duas APIs HTTP. As duas são JSON sobre HTTPS, as duas gastam o mesmo saldo de tokens, e qualquer uma basta para rodar campanhas sem nunca abrir o painel.
API de painel SMM
Um endpoint compatível com Perfect Panel. Se o seu painel já fala o protocolo SMM padrão, aponte para cá e funciona sem mexer no código.
API da plataforma
A API REST por trás do painel: navegar pelo catálogo, criar e dirigir campanhas, ler registros de entrega voto a voto, gerenciar perfis, proxies e faturas.
URL base
https://backend.toplistbot.com/api
https://backend.toplistbot.comA referência abaixo é escrita contra estes dois hosts. Qual deles você usa decide como se autentica — veja Autenticação.
Primeiros passos
De uma conta nova a uma campanha rodando em cinco passos. Tudo abaixo usa o endpoint SMM, o caminho mais rápido; a API da plataforma funciona igual assim que você tiver um JWT.
Crie uma conta
Cadastre-se e verifique seu e-mail. A verificação credita 100 tokens grátis no seu saldo, o suficiente para rodar uma campanha real antes de gastar qualquer valor.
Copie sua chave de API
Abra o painel e gere uma chave de API. Trate-a como uma senha — ela gasta seu saldo de tokens. Você pode regenerá-la quando quiser, o que invalida a anterior na hora.
Encontre o serviço desejado
Liste todos os sites em que você pode fazer pedidos. Cada item tem um id numérico de serviço e uma taxa em tokens por 1.000 ações. Anote o id do site em que quer divulgar.
cURLcurl -X POST https://backend.toplistbot.com/api/v2 -d "key=YOUR_API_KEY" -d "action=services"Faça seu primeiro pedido
Envie o id do serviço, a URL em que a campanha deve rodar e quantas ações executar. O custo é debitado na hora e a resposta traz um id de pedido.
cURLcurl -X POST https://backend.toplistbot.com/api/v2 \ -d "key=YOUR_API_KEY" \ -d "action=add" \ -d "service=9" \ -d "link=https://arena-top100.com/index.php?a=in&u=yourserver" \ -d "quantity=1000"Acompanhe a entrega
Consulte o id do pedido para ver quanto já foi entregue. Quando estiver satisfeito com o fluxo, conecte as mesmas chamadas ao seu painel ou aos seus scripts.
cURLcurl -X POST https://backend.toplistbot.com/api/v2 -d "key=YOUR_API_KEY" -d "action=status" -d "orders=184223"
Conectando uma instância Perfect Panel
Se você usa Perfect Panel ou software de painel SMM compatível, não precisa escrever código — adicione o Toplistbot como provedor com estas configurações e importe a lista de serviços.
- URL da API
- https://backend.toplistbot.com/api/v2
- Chave de API
- YOUR_API_KEY
- Método HTTP
- POST
Comece com uma quantidade pequena em um único site para confirmar que o formato do seu link é aceito antes de aumentar o volume. Um link errado também consome tokens.
Automatizar com um agente de IA
Esta página tem uma gêmea em texto puro escrita para máquinas. Dê essa URL a um agente junto com a sua chave de API e ele tem tudo o que precisa: a lista completa de endpoints, os formatos de requisição e resposta, a aritmética de preços, os códigos de erro e exemplos completos.
Referência legível por máquina
Um documento só, sem autenticação e sem JavaScript. Baixe, cole num prompt ou entregue a URL a uma ferramenta que saiba navegar.
https://toplistbot.com/llms.txtPrompt inicial
Cole isto no Claude ou em qualquer agente capaz de fazer requisições HTTP. Guarde a chave numa variável de ambiente em vez de escrevê-la na mensagem.
Read https://toplistbot.com/llms.txt — it is the complete Toplistbot API reference.
My API key is in the TOPLISTBOT_KEY environment variable. Using the API-key
surface (paths without the /api prefix):
1. list the sites in the catalog that cost under 20 tokens per 1,000 votes
2. tell me my token balance
3. propose a campaign for <my vote URL> that fits a budget of <N> tokens
Do not place the order until I confirm the cost.Uma chave de API é a credencial certa para um agente: não expira, não é afetada pela autenticação em dois fatores e girá-la pelo painel revoga o acesso na hora, se um dia precisar.
Autenticação
São duas credenciais, e qual você precisa depende do caminho, não do endpoint. Quase todo endpoint está montado duas vezes.
O prefixo /api decide a credencial
O mesmo manipulador atende os dois caminhos. Tire o prefixo /api e a API de plataforma aceita uma chave de API de longa duração; mantenha-o e o endpoint espera um JWT vindo do login.
| Caminho | Credencial | Use para |
|---|---|---|
| /api/orders/getAll | JWT | Qualquer coisa em que uma pessoa faz login |
| /orders/getAll | Chave de API | Scripts, tarefas agendadas, agentes |
Para automação, prefira os caminhos sem prefixo. Não há login, nem expiração, nem sessão para manter viva — uma chave faz tudo, e a autenticação em dois fatores nunca atrapalha.
Chave de API
Envie sua chave como campo `key` em qualquer requisição: parâmetro de consulta, campo de formulário, campo JSON ou cabeçalho `Authorization: Bearer`. Gere e gire pelo painel. Um GET em /api/v2 devolve status ok e é um jeito barato de conferir se a chave está viva.
# any of these three carry the key
curl "https://backend.toplistbot.com/orders/getAll?key=YOUR_API_KEY"
curl -X POST https://backend.toplistbot.com/orders/pause -d "key=YOUR_API_KEY" -d "id=184223"
curl https://backend.toplistbot.com/orders/getAll -H "Authorization: Bearer YOUR_API_KEY"curl https://backend.toplistbot.com/api/v2?key=YOUR_API_KEYJWT
Faça login para receber um token e envie-o como bearer token nas rotas /api. Tokens expiram, então chame /auth/refresh antes disso. Se a conta tiver autenticação em dois fatores, o login também precisa de `two_factor_code`.
curl -X POST https://backend.toplistbot.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"..."}'{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"token_type": "bearer",
"expires_in": 3600,
"user": { "id": 4211, "email": "[email protected]", "tokens": 528.41, "...": "..." }
}curl https://backend.toplistbot.com/api/orders/getAll \
-H "Authorization: Bearer YOUR_JWT"Chamar de um navegador
Todas as rotas respondem com Access-Control-Allow-Origin liberado, então uma página, uma extensão de navegador ou um agente que roda no navegador podem chamar a API direto, sem você subir um proxy. O aviso acima continua valendo: uma chave enviada ao navegador é uma chave publicada, então isso serve para as suas próprias ferramentas, não para uma página pública.
// Works from a page, an extension, or a browser-based agent.
const sites = await fetch(
'https://backend.toplistbot.com/orders/getAllWebsites'
).then(r => r.json())Sua chave de API gasta saldo real de tokens. Mantenha-a no servidor: qualquer chave enviada ao navegador ou commitada num repositório deve ser tratada como comprometida e girada pelo painel.
Tokens e preços
As campanhas são pagas em tokens, comprados antecipadamente. Cada site publica uma taxa — quantos tokens custam 1.000 ações de campanha ali — retornada como `rate` pela ação services.
cost_in_tokens = (rate * quantity) / 1000Um site com taxa 13 custa 13 tokens por 1.000 ações, então um pedido de 500 custa 6,5 tokens. O custo é debitado quando o pedido é aceito, e o cancelamento devolve o restante não gasto.
As respostas de balance e status informam um campo de moeda USD por compatibilidade com o Perfect Panel, mas o valor é um saldo de tokens, não dólares. Trate o número como tokens.
API de painel SMM
Um endpoint faz tudo. Envie um campo `action` em cada POST para escolher a operação; toda requisição também leva sua `key`.
https://backend.toplistbot.com/api/v2| Ação | Parâmetros |
|---|---|
services | — |
add | service, link, quantity, interval? |
status | orders |
balance | — |
cancel | orders |
`refill` e `refill_status` são aceitas por compatibilidade e as duas respondem "não implementado". Nada aqui é recarregável; faça um novo pedido.
action=services
Lista todos os sites em que você pode fazer pedidos, com a taxa atual e os limites. Use o id `service` nas suas chamadas add.
curl -X POST https://backend.toplistbot.com/api/v2 \
-d "key=YOUR_API_KEY" \
-d "action=services"[
{
"service": 9,
"name": "arena-top100.com 1000 upvotes",
"type": "Default",
"category": "Votes",
"rate": 15,
"min": 1,
"max": 50000,
"refill": false,
"cancel": true
}
]`rate` é em tokens por 1.000 ações. `min` é 1 e `max` é 50000 para todos os serviços.
action=add
Cria uma campanha e debita o custo do seu saldo imediatamente.
| Parâmetro | Tipo | Descrição |
|---|---|---|
keyobrigatório | string | Sua chave de API. |
actionobrigatório | string | Deve ser `add`. |
serviceobrigatório | integer | Id do serviço vindo da ação services. |
linkobrigatório | url | A URL em que a campanha vai rodar. Precisa ser uma URL válida. |
quantityobrigatório | integer | Número de ações a executar, entre 1 e 50000. |
interval | integer | Ações por hora. Padrão 15, limite de 4000, e não pode ultrapassar o máximo do próprio site. |
curl -X POST https://backend.toplistbot.com/api/v2 \
-d "key=YOUR_API_KEY" \
-d "action=add" \
-d "service=9" \
-d "link=https://arena-top100.com/index.php?a=in&u=yourserver" \
-d "quantity=1000" \
-d "interval=60"{
"order_id": 184223
}action=status
Retorna o progresso de um ou mais pedidos. Passe um único id para um objeto simples, ou uma lista separada por vírgulas.
curl -X POST https://backend.toplistbot.com/api/v2 \
-d "key=YOUR_API_KEY" \
-d "action=status" \
-d "orders=184223"{
"charge": 13.5,
"start_count": 0,
"status": "Completed",
"remains": 1000,
"currency": "USD"
}Com vários ids, a resposta é indexada pelo id do pedido, e pedidos desconhecidos ou de outra conta retornam uma entrada de erro em vez de derrubar a requisição inteira.
{
"184223": { "charge": 13.5, "start_count": 0, "status": "Completed", "remains": 1000, "currency": "USD" },
"184224": { "error": "Incorrect order ID" }
}Leia `remains`, não `status`
`status` é sempre o literal "Completed". O campo existe porque todo cliente Perfect Panel exige, e painéis tratam qualquer outro valor como candidato a recarga — algo que esta plataforma não oferece. O progresso está nos números: `remains` são os votos aceitos que faltam entregar, então `remains == 0` significa que o pedido terminou. `start_count` é o que já foi entregue e `charge` é o que custou até agora. Ambos são medidos contra a taxa de aceitação do site, ou seja, contam os votos que você comprou e não as tentativas brutas.
`status` e `cancel` aceitam no máximo 100 ids de pedido por chamada. Agrupe em vez de iterar: uma chamada com 100 ids é bem mais barata para os dois lados do que 100 chamadas.
action=balance
Retorna seu saldo restante de tokens.
curl -X POST https://backend.toplistbot.com/api/v2 \
-d "key=YOUR_API_KEY" \
-d "action=balance"{
"balance": 528.41,
"currency": "USD"
}action=cancel
Interrompe um pedido e devolve o restante não gasto ao seu saldo. Pedidos concluídos não podem ser cancelados.
curl -X POST https://backend.toplistbot.com/api/v2 \
-d "key=YOUR_API_KEY" \
-d "action=cancel" \
-d "orders=184223,184224"[
{ "order": "184223", "cancel": 1, "refund": 4.5 },
{ "order": "184224", "cancel": { "error": "Incorrect order ID" } }
]API da plataforma
A mesma API REST que o painel usa. Os caminhos abaixo estão na forma com chave de API, sem o prefixo /api. Coloque /api e troque a chave por um JWT para usar a forma com sessão; endpoints marcados como JWT só existem sob /api.
Catálogo e descoberta
Público, sem credencial. getAllWebsites é o endpoint por onde começar: traz o id, o preço, o teto por hora e a taxa de aceitação de que você precisa para precificar e dimensionar um pedido.
- GET
/orders/getAllWebsitesPúblicaO catálogo completo: cada site com tarifas, limites e metadados - GET
/orders/getAllBasicWebsitesDetailsPública20 nomes de site aleatórios, para widgets e autocompletes - POST
/orders/getWebsiteDetailsByNamePúblicaUm site pelo nome exato - POST
/products/getSuggestionsPúblicaSites relacionados a um conjunto de ids - GET
/products/demand?days=30PúblicaO quanto cada site foi pedido recentemente - GET
/products/tokensPúblicaPacotes de tokens que você pode comprar - POST
/products/suggestChave de APIPeça para adicionarmos um site novo - GET
/api/news/timelinePúblicaNovidades do produto
curl "https://backend.toplistbot.com/orders/getAllWebsites"Peça menos
O catálogo inteiro tem cerca de 665 KB em 396 sites, e dois campos com os quais você nunca vai fazer um pedido respondem por metade disso: um bloco JSON de popularidade e a descrição de marketing. Projete só os campos que usa para pedir e descarte os sites inativos e ele cai para uns 40 KB.
# The whole catalog is ~665 KB across 396 sites.
# Projected to what you actually order with: ~40 KB.
curl -s "https://backend.toplistbot.com/orders/getAllWebsites" \
| jq '[.[]
| select(.active == 1)
| {id, name, price_per_1000, max_per_hour, accept_rate, subscribeable}]'Para um agente de IA essa é a diferença entre cerca de 170.000 tokens e 10.000: entre a primeira chamada funcionar ou esgotar a janela de contexto. Projete antes de processar.
Conta e sessões
O cadastro precisa de navegador: é protegido por um desafio da Cloudflare. Cadastre-se uma vez em app.toplistbot.com e automatize todo o resto.
- POST
/api/auth/registerPúblicaCriar uma conta: só por navegador, protegido por captcha - POST
/api/auth/loginPúblicaTrocar credenciais por um JWT - POST
/api/auth/refreshJWTEmitir um JWT novo a partir de um que está expirando - POST
/api/auth/logoutJWTInvalidar o JWT atual - GET
/api/auth/user-profileJWTA conta logada, com saldo e chave de API - GET
/api/userJWTO mesmo objeto de usuário, num caminho mais curto - GET
/api/api_tokenChave de APIResolver uma chave de API para o dono: use para validar uma chave - POST
/api/auth/reset-api-keyJWTGirar sua chave de API; a antiga morre na hora - POST
/api/auth/fingerprintJWTRegistrar uma impressão de navegador na conta - POST
/api/auth/ipJWTRegistrar o IP atual da conta - POST
/api/auth/forgot-passwordPúblicaEnviar por e-mail um link de redefinição, válido por 60 minutos - POST
/api/auth/reset-passwordPúblicaDefinir uma senha nova com o token enviado por e-mail
Dois fatores e login
Os dois fatores protegem o login por senha. Não valem para chaves de API, e é por isso que uma chave é a melhor credencial para trabalho não assistido.
- POST
/api/2fa/enableJWTIniciar o cadastro: devolve o segredo, a URL do QR e os códigos de recuperação - POST
/api/2fa/verifyJWTConfirmar um código de seis dígitos e ligar os dois fatores - POST
/api/2fa/disableJWTDesligar os dois fatores - POST
/api/account/verification/requestJWTEnviar um link de verificação ao endereço logado - GET
/api/account/verification/confirm?token=PúblicaExibir a página de confirmação: não escreve nada - POST
/api/account/verification/confirmPúblicaEfetivar a verificação - GET
/api/auth/googlePúblicaIniciar login com Google - GET
/api/auth/google/callbackPúblicaRetorno do login com Google - GET
/api/auth/discordPúblicaIniciar login com Discord - GET
/api/auth/discord/callbackPúblicaRetorno do login com Discord
Preferências e avisos
Chaves de e-mail e notificação, e o histórico de avisos da conta.
- GET
/api/user/email-preferencesJWTEstado da inscrição em e-mails de marketing - POST
/api/user/email-preferencesJWTAlterar - GET
/api/user/notification-preferencesJWTPreferência de avisos de voto ao vivo - POST
/api/user/notification-preferencesJWTAlterar: precisa ser um booleano JSON de verdade - GET
/api/user/alerts?limit=20JWTAvisos da conta, do mais recente ao mais antigo, paginados por ?before - POST
/api/user/alerts/readJWTMarcar um aviso como lido - POST
/api/user/alerts/dismissJWTDispensar um aviso - GET
/api/email/unsubscribe?token=PúblicaCancelamento em um clique a partir de um token enviado por e-mail
Campanhas
Criar campanhas, dirigi-las enquanto rodam e encerrá-las. É o coração da API de plataforma.
- GET
/orders/getAllChave de APISuas campanhas, da mais recente à mais antiga, com o site junto - GET
/orders/get/{id}Chave de APIUma campanha - POST
/orders/checkoutChave de APICriar campanhas e cobrar do saldo - POST
/orders/updateChave de APIEditar uma campanha - POST
/orders/pauseChave de APIPausar uma campanha em andamento - POST
/orders/unpauseChave de APIRetomar uma campanha pausada - POST
/orders/archiveChave de APIArquivar uma campanha - POST
/orders/unarchiveChave de APIRestaurar uma campanha arquivada - PATCH
/orders/updateLimitChave de APIDefinir ou remover o teto diário de votos
POST /orders/checkout
O corpo é um array JSON de linhas de carrinho no nível superior, não um objeto. Cada linha é uma campanha. O carrinho inteiro é validado antes de qualquer cobrança, e a cobrança mais as inserções são uma única transação: um pedido acontece inteiro ou não acontece.
Uma linha de quantidade fixa
O caso comum: entregar um número definido de votos a uma URL.
| Parâmetro | Tipo | Descrição |
|---|---|---|
idobrigatório | integer | Id do site, de /orders/getAllWebsites. |
amountobrigatório | integer | Votos a entregar. 0 ou mais, até 2.147.483.647. |
ownNameobrigatório | url | A URL de voto. Guardada como o campo `url` do pedido. |
custom_max_per_hour | integer | Teto de entrega, limitado ao máximo do próprio site. |
extra_col | string | Campo de texto livre que segue com o pedido. |
curl -X POST "https://backend.toplistbot.com/orders/checkout?key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"id": 9,
"amount": 1000,
"ownName": "https://arena-top100.com/index.php?a=in&u=yourserver",
"custom_max_per_hour": 60
}
]'200 OK
Successfully purchased with token balanceUma linha de assinatura
Para sites cujo indicador `subscribeable` vale 1. O preço vem do subscription_price_1d do site multiplicado pelos dias e pelo desconto do nível: Weekly é 0,90, Monthly é 0,80 e qualquer outro é 1,00. A quantidade entregue é derivada no servidor a partir do próprio subscription_speed do site, então nada do que você envia muda isso.
[
{
"type": "subscription",
"website": { "id": 9 },
"subscription_days": 30,
"tier": { "name": "Monthly" },
"url": "https://arena-top100.com/index.php?a=in&u=yourserver"
}
]Respostas
200Todas as linhas foram criadas e o saldo foi cobrado. O corpo é texto puro.400O corpo não era JSON válido.402Saldo insuficiente. A mensagem diz quantos tokens faltam e nada foi cobrado.422Uma ou mais linhas estão erradas. Nada foi cobrado.429O mesmo carrinho foi enviado nos últimos 60 segundos. Tente de novo após a espera indicada.
Um 422 aponta a linha problemática: os erros são indexados como items.[index].[field], então um carrinho com três linhas ruins se resolve numa ida e não em três.
{
"errors": {
"items.2.amount": ["Enter 0 or more votes; a negative amount is not allowed."]
}
}POST /orders/update
`id` é obrigatório; envie só os campos que está mudando. Pedidos de assinatura não podem ser modificados.
| Parâmetro | Tipo | Descrição |
|---|---|---|
idobrigatório | integer | A campanha a editar. |
amount_to_do | integer | Novo total de votos. Aumentar cobra a diferença, diminuir devolve, e há 30 segundos de espera entre mudanças. |
url | url | A URL de voto. |
custom_name | string | Seu próprio rótulo para a campanha. |
custom_max_per_hour | integer | Teto de entrega. |
username_profile_id | integer | Vincular um perfil de voto. |
proxy_profile_id | integer | Vincular um perfil de proxy. |
http_referral | url | Referenciador a enviar com cada voto. |
extra_col | string | Campo de texto livre. |
curl -X POST "https://backend.toplistbot.com/orders/update?key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"id":184223,"amount_to_do":2000,"custom_name":"EU launch"}'Teto diário
`type: "delete"` remove o teto. Nesse caso o validador ainda exige `max_votes_per_day`: mande qualquer inteiro.
curl -X PATCH "https://backend.toplistbot.com/orders/updateLimit?key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"id":184223,"max_votes_per_day":500,"type":"set"}'Registros e análises
Dados de entrega, voto a voto e agregados. Leem um banco de registros separado e são mais lentos que o resto da API: consulte em minutos, não em segundos.
- GET
/orders/logs/{id}Chave de APIRegistro de entrega voto a voto de uma campanha - GET
/orders/graph/{id}Chave de APISérie temporal de uma campanha, pronta para gráfico - GET
/api/orders/graph/summaryJWTUma série somando todas as suas campanhas - GET
/orders/grouped/usernames/{id}Chave de APIEntregas agrupadas pelo usuário que votou - POST
/orders/averageChave de APIEntrega média de várias campanhas - GET
/api/logs/{id}/filtered-graphJWTSérie temporal filtrada
Perfis de voto e proxy
Um perfil de voto é uma lista nomeada de usuários com que a campanha vota. Um perfil de proxy é uma lista de países permitidos para os IPs usados. Vincule qualquer um deles a uma campanha com username_profile_id ou proxy_profile_id em /orders/update.
- GET
/advanced/profile/getChave de APISeus perfis de voto - GET
/advanced/profile/get/{id}Chave de APIUm perfil de voto - POST
/advanced/profile/createChave de APICriar um perfil de voto, ou sobrescrever um por id - DELETE
/advanced/profile/delete/{id}Chave de APIExcluir um perfil de voto - GET
/advanced/profile/proxy/getChave de APISeus perfis de proxy - GET
/advanced/profile/proxy/get/{id}Chave de APIUm perfil de proxy - POST
/advanced/profile/proxy/createChave de APICriar um perfil de proxy, ou sobrescrever um por id - DELETE
/advanced/profile/proxy/delete/{id}Chave de APIExcluir um perfil de proxy
Tokens do Discord
Para listas que autenticam votantes pelo Discord. Adicionar o mesmo token duas vezes é recusado como duplicata.
- GET
/api/discord-tokensJWTSeus tokens do Discord - POST
/api/discord-tokensJWTAdicionar um token - GET
/api/discord-tokens/statsJWTUso acumulado dos seus tokens - GET
/api/discord-tokens/{id}JWTUm token - PATCH
/api/discord-tokens/{id}JWTAlterar um token ou seu estado ativo - DELETE
/api/discord-tokens/{id}JWTRemover um token - PUT
/api/discord-tokens/{id}/toggleJWTAlternar um token entre ativo e inativo
Cobrança e pagamentos
Comprar tokens sempre termina numa página de pagamento hospedada, então recarregar não pode ser totalmente automático. Tudo depois da recarga pode.
- GET
/invoices/getChave de APIHistórico de cobrança - GET
/api/subscriptions/subscriptionsJWTAssinaturas ativas - GET
/products/tokensByUserChave de APIPacotes de tokens com o preço da sua conta - POST
/company/getChave de APISeu endereço de cobrança - POST
/company/createChave de APIDefinir: country, region, city, address, postalCode - GET
/api/stripe/checkout?product_id=JWTUma URL do Stripe Checkout para um pacote de tokens - GET
/api/stripe/subscription?plan=JWTUma URL do Stripe Checkout para um plano - GET
/api/stripe/portalJWTUma URL do portal de cobrança do Stripe - GET
/api/stripe/documentsJWTFaturas e recibos do Stripe - GET
/coinpayments/checkoutChave de APIUma URL de pagamento em cripto
Carrinho salvo
O carrinho do painel, guardado no servidor para sobreviver a uma troca de dispositivo. Você não precisa dele para fazer pedidos: /orders/checkout aceita o carrinho na própria requisição.
- GET
/api/cartJWTO carrinho salvo - PUT
/api/cartJWTSubstituir - POST
/api/cartJWTSubstituir, igual ao PUT - DELETE
/api/cartJWTEsvaziar
Superfícies internas
Existem para o Stripe, o agendador de tarefas e o desafio antiabuso do cadastro. São autenticadas por segredos compartilhados ou assinaturas e não fazem parte da superfície de integração: estão aqui só para o inventário ficar completo.
- POST
/api/stripe/webhookEventos de pagamento do Stripe, autenticados por assinatura - POST
/api/jobs/tickExecuta as tarefas pendentes, autenticado por segredo compartilhado - POST
/api/pow/challengeDesafio de prova de trabalho do cadastro - POST
/api/logs/updateRastreador de atividade de e-mail - POST
/api/order/{email}Cria um pedido em outra conta: só para a lista de administradores - GET
/reset-password/{token}A antiga página de redefinição renderizada no servidor, mantida pelos links já enviados - GET
/PúblicaVerificação de saúde
Formatos de resposta
Quase tudo o que você vai ler vem em dois objetos: o site, devolvido pelos endpoints de catálogo, e a campanha, devolvida pelos de pedidos. Cada um tem cerca de quarenta colunas; as tabelas abaixo são as que uma integração realmente precisa.
Três campos chegam como strings JSON mesmo contendo números: accept_rate e timeout no site, e custom_max_per_hour na campanha. Converta antes de fazer contas, ou você vai concatenar strings em vez de somar.
{
"accept_rate": "70", // string, not number
"timeout": "150000", // string, not number
"custom_max_per_hour": "60" // string, not number
}O objeto site
Devolvido por /orders/getAllWebsites e /orders/getWebsiteDetailsByName, e embutido em cada campanha como `website`.
| Parâmetro | Tipo | Descrição |
|---|---|---|
id | integer | O id do site. Envie como `id` numa linha de carrinho, ou como `service` no endpoint SMM. |
name | string | Nome exibido, e a string exata que /orders/getWebsiteDetailsByName compara. |
price_per_1000 | number | Tokens por 1.000 votos aceitos. É o número que a fórmula de custo usa. |
accept_rate | string | Percentual dos votos enviados que são aceitos. Todo cálculo de progresso e de reembolso depende dele. |
max_per_hour | integer | O teto de entrega do próprio site. Tanto custom_max_per_hour quanto o interval do SMM são limitados a ele. |
active | integer | 1 significa que dá para pedir. Sites inativos também vêm na resposta, então filtre você mesmo. |
vote_reset_time | integer | Horas até a mesma identidade poder votar de novo. |
speed_changeable | integer | 1 significa que o site respeita uma velocidade de entrega personalizada. |
referer_must_be_set | integer | 1 significa que http_referral precisa estar definido na campanha. |
optional_data_possible | integer | 1 significa que o site aceita o campo optional_data da campanha. |
track_votes | integer | 1 significa que há registros de entrega voto a voto para campanhas neste site. |
subscribeable | integer | 1 significa que linhas de assinatura são aceitas. |
subscription_price_1d | number | Tokens por dia de assinatura, antes do desconto do nível. |
subscription_speed | integer | Votos por hora que uma assinatura entrega. A quantidade é derivada disso no servidor, nunca do seu pedido. |
Os campos omitidos aqui alimentam a interface do próprio painel. Leia se quiser, mas eles não fazem parte do contrato de integração e podem mudar sem aviso.
O objeto campanha
Devolvido por /orders/getAll e /orders/get/. Repare no que falta: não existe campo de status.
| Parâmetro | Tipo | Descrição |
|---|---|---|
id | integer | O id da campanha. Todos os endpoints de Campanhas o recebem como `id`. |
vote_website_id | integer | O site em que esta campanha roda. |
website | object | O objeto site completo, embutido. Presente em /orders/getAll e ausente em /orders/get/. |
url | string | A URL de voto: o `ownName` que você enviou no checkout. |
custom_name | string | Seu próprio rótulo para a campanha, ou null. |
amount_to_do | integer | Votos aceitos comprados. Conta votos aceitos, não tentativas. |
amount_done | integer | Votos enviados até agora. Unidade diferente de amount_to_do: veja a seção de progresso. |
running | integer | 1 entregando, 0 pausada. |
done | integer | 1 significa encerrada: cancelada, reembolsada e com as duas quantidades zeradas. Não é um indicador de conclusão. |
archive | integer | 1 significa arquivada. Campanhas arquivadas continuam sendo devolvidas por /orders/getAll. |
custom_max_per_hour | string | Seu teto de entrega para esta campanha, como string. |
max_votes_per_day | integer | Teto diário de votos, ou null quando não há teto. |
is_subscription | integer | 1 significa assinatura. Assinaturas não podem ser editadas após a compra. |
paused_unpaused | datetime | Quando a campanha foi pausada, retomada ou redimensionada pela última vez. É o que inicia a espera de 30 segundos entre edições. |
Os campos omitidos aqui alimentam a interface do próprio painel. Leia se quiser, mas eles não fazem parte do contrato de integração e podem mudar sem aviso.
Está rodando? Já terminou?
Uma campanha não tem campo de status, então você deduz o estado a partir de quatro colunas. Avalie estas condições em ordem e fique com a primeira que bater.
| Teste | Significa |
|---|---|
1done === 1 | Cancelada. O restante não gasto foi reembolsado, as duas quantidades foram zeradas e ela foi arquivada. |
2running === 0 | Pausada por você. Retome com /orders/unpause. |
3remaining_accepted === 0 | Tudo o que foi comprado já foi entregue. |
4running === 1 | Rodando normalmente. |
5archive === 1 | Escondida no painel, mas ainda devolvida por /orders/getAll. Filtre se quiser bater com o que o painel mostra. |
A ordem importa. Cancelar define done e archive juntos, então testar archive primeiro mostraria uma campanha cancelada como apenas arquivada, e testar o restante antes de running mostraria uma campanha pausada como se estivesse entregando.
Progresso e reembolsos
amount_to_do conta votos aceitos; amount_done conta envios. Só accept_rate por cento dos envios são aceitos, então as duas estão em unidades diferentes e subtrair uma da outra direto está errado.
Este é o erro de integração mais comum, e ele falha em silêncio: os números continuam plausíveis e a barra de progresso simplesmente está errada. Com taxa de aceitação de 70 por cento, uma campanha concluída aparece como 70 por cento; com 50 por cento, uma campanha entregue pela metade aparece como se nada tivesse acontecido. Converta envios em votos aceitos primeiro, sempre.
// accept_rate arrives as a STRING, and it is per-site, not global.
const rate = Number(order.website.accept_rate)
// amount_done counts SUBMISSIONS; amount_to_do counts ACCEPTED votes.
// Convert before comparing them.
const delivered = order.amount_done * rate / 100
const remaining = Math.max(order.amount_to_do - delivered, 0)
const percent = 100 * delivered / order.amount_to_do
// What cancelling right now would put back on your balance:
const refund = (remaining / 1000) * order.website.price_per_1000A mesma conta precifica um cancelamento: o reembolso é o restante não gasto ao preço de tabela do site, então dá para saber quanto vale parar uma campanha antes de decidir.
Uma campanha de ponta a ponta
Seis chamadas, uma chave de API, sem navegador e sem login. O mesmo pelo endpoint SMM são três chamadas — services, add, status — e não toca na API de plataforma.
KEY=YOUR_API_KEY
BASE=https://backend.toplistbot.com
# 1. What can I order, and what does it cost?
curl -s "$BASE/orders/getAllWebsites" \
| jq '.[] | {id, name, price_per_1000, max_per_hour}'
# 2. What can I afford?
curl -s -X POST "$BASE/api/v2" -d "key=$KEY" -d "action=balance"
# 3. Launch it. cost = price_per_1000 * amount / 1000
curl -s -X POST "$BASE/orders/checkout?key=$KEY" \
-H "Content-Type: application/json" \
-d '[{"id":9,"amount":1000,
"ownName":"https://arena-top100.com/index.php?a=in&u=me",
"custom_max_per_hour":60}]'
# 4. Find the campaign that was just created.
curl -s "$BASE/orders/getAll?key=$KEY" | jq '.[0] | {id, url, amount_to_do, amount_done}'
# 5. Watch it. Poll every few minutes.
curl -s "$BASE/orders/graph/184223?key=$KEY"
# 6. Slow it down, or stop it.
curl -s -X PATCH "$BASE/orders/updateLimit?key=$KEY" \
-H "Content-Type: application/json" -d '{"id":184223,"max_votes_per_day":200,"type":"set"}'
curl -s -X POST "$BASE/orders/pause?key=$KEY" \
-H "Content-Type: application/json" -d '{"id":184223}'Erros
Os erros vêm com o status HTTP correspondente. Falhas de validação retornam um objeto `errors` indexado pelo nome do campo.
400A requisição não pôde ser lida: JSON malformado, ou uma ação que o endpoint SMM não conhece.401Credencial ausente, expirada ou errada.402Saldo insuficiente. Nada foi cobrado.403Autenticado, mas sem permissão para isso.404Registro inexistente, incluindo um que pertence a outra pessoa.409Conflita com o estado atual da conta, como ligar os dois fatores duas vezes.422A validação falhou. O corpo nomeia cada campo.429Limite de requisições. A mensagem diz quanto esperar.500Culpa nossa. Nada foi cobrado.503Uma dependência está indisponível. Tente mais tarde.
{
"errors": {
"quantity": ["The quantity must be at least 1."]
}
}Quando o corpo da requisição era um array, as chaves de erro carregam o índice da linha que falhou.
Alguns endpoints respondem em texto puro e não em JSON: /orders/checkout, /orders/pause e /orders/updateLimit entre eles. Decida pelo código de status, não pelo formato do corpo.
Limites de requisições
Um 429 sempre diz quanto esperar. Respeite em vez de tentar de novo às cegas.
- O mesmo carrinho é aceito no máximo uma vez a cada 60 segundos.
- O total de votos de uma campanha pode mudar uma vez a cada 30 segundos.
- Tentativas de login são limitadas por endereço e por IP.
- Redefinição de senha: 3 por endereço e 10 por IP a cada 15 minutos.
- `status` e `cancel` aceitam no máximo 100 ids de pedido por chamada.
- Acompanhe o progresso em minutos, não em segundos. A entrega é medida em votos por hora.
Limites e observações
- A quantidade do pedido deve ficar entre 1 e 50000 ações.
- O intervalo é 15 por hora por padrão e tem teto de 4000. Pedir mais que o máximo do próprio site é rejeitado com um 400 informando o limite.
- As ações `refill` e `refill_status` não estão implementadas — crie um novo pedido em vez disso.
- O campo `status` é sempre o literal "Completed" e não é sinal de progresso. Use `remains == 0` para saber que um pedido terminou, e `start_count` para o que foi entregue.
- Assinaturas não podem ser editadas após a compra: pause ou cancele.
- Os sites de listagem definem suas próprias regras e as mudam com o tempo. Você é responsável por garantir que seu uso esteja de acordo com os termos de qualquer site em que divulgar. Não prometemos nenhuma colocação ou posição específica.
