API
Tudo o que o painel faz está disponível por meio de duas APIs separadas. As duas usam a mesma conta, o mesmo saldo e o mesmo catálogo; o que muda é o formato e o que cada uma consegue fazer.
Tudo o que o painel faz está disponível por meio de duas APIs separadas. As duas usam a mesma conta, o mesmo saldo e o mesmo catálogo; o que muda é o formato e o que cada uma consegue fazer.
Por que existem duas APIs?
A API clássica de revenda (v2), usada pelo setor inteiro, envia um formulário para um único endpoint e sempre responde HTTP 200. Esse é exatamente o formato que os softwares de painel prontos esperam, então ele continua igual. Já quem escreve o próprio sistema vivia esbarrando nas limitações desse formato: não dava para distinguir os erros, o catálogo chegava em uma peça só e o status do pedido precisava ser consultado sem parar. A v3 foi escrita para esse público.
Comparação
| Recurso | Legacy (v2) | Nova (v3) |
|---|---|---|
| Formato | Um único endpoint, envio de formulário, parâmetro action | REST orientado a recursos, corpo em JSON |
| Código HTTP | Sempre 200, mesmo quando falha | Códigos reais (400, 401, 402, 404, 409, 429, 503) |
| Erros | Texto livre | type + code estável + mensagem localizada + param + doc_url |
| Status do pedido | Somente texto localizado | Valor de máquina estável mais um rótulo de exibição separado |
| Descrição do serviço | Não tem | Descrição em 16 idiomas, tempo médio, plataforma, categoria |
| Campos do pedido | Deduzidos pelo nome do tipo | Cada serviço publica o próprio esquema de campos |
| Unidade de preço | Não informada (fonte de erro de 1000x nos pacotes) | Informada explicitamente como per_1000 ou per_order |
| Catálogo | Todos os serviços em uma única resposta | Filtros mais paginação por cursor |
| Proteção contra duplicidade | Não tem | Idempotency-Key |
| Aviso de status | Consulta contínua | Webhooks assinados ou stream de eventos |
| Esquema | Não tem | OpenAPI 3.1 |
| Idiomas | Inglês e turco (endereços separados) | 16 idiomas (por cabeçalho ou por parâmetro) |
| Qualidade do serviço | Nenhuma | Pontuação, confiança e evidências por serviço; lista ranqueada |
Qual das duas eu devo usar?
Escolha a API legacy se você usa um software de painel pronto, um bot ou um painel de revenda. A maioria pede apenas que você troque o endereço da API e a chave, e começa a funcionar em poucos minutos.
Escolha a v3 se você está escrevendo o seu próprio aplicativo, a sua loja ou a sua automação. Tratamento de erros, proteção contra duplicidade e notificações já vêm prontos, e você consegue gerar o formulário de pedido direto do esquema do serviço.
Primeiros passos
- 1Crie uma chave de API na aba Chaves.
- 2Baixe a lista de serviços e veja o id e o esquema de campos do serviço que você vai usar.
- 3Valide o pedido primeiro com preview e só depois crie de fato.
- 4Cadastre um webhook, ou leia o stream de eventos, para acompanhar as mudanças de status.
Uma API REST desenhada para desenvolvedores que estão construindo o próprio sistema: caminhos orientados a recursos, códigos de status HTTP reais, erros legíveis por máquina e notificações assinadas.
Endereço base
Todos os caminhos são acrescentados a esse endereço. A versão fica no caminho: se algum dia for necessária uma mudança que quebre compatibilidade, um caminho novo (v4) é publicado e o atual continua funcionando sem alteração nenhuma. A data de publicação do contrato volta no cabeçalho X-Api-Version em toda resposta.
https://panelfollows.com/api/v3Autenticação
Envie a sua chave de API como token Bearer no cabeçalho Authorization. Como alternativa, o cabeçalho X-Api-Key também é aceito.
GET https://panelfollows.com/api/v3/account
Authorization: Bearer pf_live_...A sua chave legacy atual também funciona na v3, então você já pode testar agora. Em produção, use uma chave v3: ela pode ser rotulada, revogada uma a uma e nunca fica guardada em texto puro.
Início rápido
curl https://panelfollows.com/api/v3/services?limit=5 \
-H "Authorization: Bearer YOUR_API_KEY"Idioma
O idioma da resposta é escolhido pelo cabeçalho Accept-Language ou pelo parâmetro ?lang=; o parâmetro tem prioridade sobre o cabeçalho. Nome do serviço, descrição do serviço, nome da categoria, rótulo de status do pedido, rótulos dos campos do pedido e mensagens de erro voltam todos no idioma escolhido.
Os valores de máquina não mudam em nenhum idioma: error.code, order.status, service.type e currency são sempre os mesmos. Escreva as suas condições em cima deles e mostre o texto para o usuário.
Accept-Language: tr
# veya
GET https://panelfollows.com/api/v3/services?lang=trFormato de requisição e resposta
O corpo da requisição é JSON (application/json); para testes rápidos, form-urlencoded também é aceito. As respostas são JSON: um recurso individual vem como objeto simples e as listas vêm em um envelope com data, has_more e next_cursor. Todo objeto carrega um campo object informando o próprio tipo.
Os valores são retornados como STRINGS decimais ("1.2340"), e não como ponto flutuante. Converta para um tipo decimal do seu lado, para não perder centavos. A moeda é USD.
Os carimbos de data e hora seguem o formato RFC 3339 (2026-08-21T00:24:45.255Z).
Erros
Quando algo falha, volta um código de status HTTP real e o corpo traz um único objeto error. O seu código deve olhar para error.code: esse valor é estável e não muda conforme o idioma.
HTTP/1.1 400 Bad Request
Content-Type: application/json
X-Request-Id: req_0c858d8af7f65eca001b2f5a
{
"object": "error",
"error": {
"type": "invalid_request_error",
"code": "quantity_out_of_range",
"message": "Miktar, bu servisin izin verdiği aralığın dışında.",
"param": "quantity",
"doc_url": "https://panelfollows.com/api-docs#error-quantity_out_of_range",
"request_id": "req_0c858d8af7f65eca001b2f5a"
}
}| type | Classe geral: dá para tentar de novo ou o erro é seu. |
| code | Valor de máquina estável. Escreva as suas condições em cima dele. |
| message | Texto legível por pessoas, no idioma que você escolheu. |
| param | Nome do campo que causou o erro, quando existe um. |
| doc_url | Link para a seção exata desta documentação. |
| request_id | A única referência que você deve informar ao acionar o suporte. |
Limite de requisições
600 requisições por minuto por chave, mais 900 por minuto por IP. Toda resposta traz RateLimit-Limit, RateLimit-Remaining e RateLimit-Reset, então você consegue reduzir o ritmo antes de bater no teto. Passar do limite devolve 429 com o cabeçalho Retry-After.
Paginação
As listas são paginadas por cursor. Envie limit para o tamanho da página (no máximo 500) e starting_after com o id do último item da página anterior. Siga até has_more virar false; next_cursor entrega o cursor pronto para a próxima chamada. Um limit fora da faixa não é cortado em silêncio, ele devolve erro: o corte silencioso faz o cliente acreditar que baixou tudo.
Proteção contra duplicidade (Idempotency-Key)
Ao criar um pedido, adicione à requisição um cabeçalho Idempotency-Key aleatório. Se a conexão cair e você tentar de novo com a mesma chave, nenhum segundo pedido é aberto: a resposta da primeira requisição volta igual, com o cabeçalho Idempotent-Replay: true. Os registros ficam guardados por 24 horas.
Enviar a mesma chave com um corpo DIFERENTE devolve 409 idempotency_key_reuse. Isso quase sempre indica que a geração de chaves está quebrada do lado do cliente. Uma requisição que falhou não queima a chave: corrija o problema e tente de novo com ela mesma.
Criando um pedido
curl -X POST https://panelfollows.com/api/v3/orders \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8f14e45f-ea3a-4b1c-9c1e-2b0d5c6a7e91" \
-d '{
"service": 1234,
"link": "https://instagram.com/username",
"quantity": 1000
}'Esquema de campos do serviço
Cada serviço publica no array fields quais campos ele pede no pedido: nome do campo, tipo, se é obrigatório, os limites dele e ainda um rótulo com a descrição no idioma do usuário. Quando um campo tem determines_quantity igual a true, a quantidade é calculada pelo número de linhas desse campo.
// Servisin kendi alan şemasından formu OTOMATİK üretmek:
// hiçbir servis tipini koda gömmeniz gerekmez.
const res = await fetch("https://panelfollows.com/api/v3/services/1234", {
headers: { Authorization: "Bearer YOUR_API_KEY", "Accept-Language": "tr" },
});
const service = await res.json();
for (const field of service.fields) {
renderInput({
name: field.name,
label: field.label, // kullanıcının dilinde
hint: field.description, // kullanıcının dilinde
required: field.required,
type: field.type, // url | integer | string | text_lines
min: field.min,
max: field.max,
// true ise miktarı bu alanın satır sayısı belirler
countsLines: field.determines_quantity === true,
});
}O objeto serviço
{
"object": "service",
"id": 1234,
"name": "Instagram Takipçi | Türk | 30 gün telafi",
"description": "Gerçek hesaplardan Türk takipçi. Başlangıç 0-1 saat.",
"type": "default",
"platform": "instagram",
"category": { "slug": "instagram-takipci", "name": "Instagram Takipçi" },
"pricing": {
"rate": "1.2340",
"currency": "USD",
"unit": "per_1000",
"unit_note": "Fiyat 1000 adet içindir."
},
"limits": { "min": 100, "max": 100000 },
"features": { "refill": true, "cancel": false, "dripfeed": true },
"average_time_seconds": 4320,
"fields": [
{
"name": "link",
"type": "url",
"required": true,
"label": "Bağlantı",
"description": "Gönderimin yapılacağı profilin herkese açık adresi."
},
{
"name": "quantity",
"type": "integer",
"required": true,
"label": "Miktar",
"description": "Kaç adet gönderileceği.",
"min": 100,
"max": 100000
}
],
"is_active": true,
"updated_at": "2026-08-20T09:15:00.000Z"
}Prévia do pedido (execução seca)
POST /orders/preview valida o pedido e calcula a cobrança SEM criar nada. Você pode mostrar o preço para o seu cliente e conferir antes se o seu saldo cobre o valor. Nada é debitado do saldo e o provedor não é acionado.
Pedidos em lote
Com POST /orders/batch você envia até 50 pedidos em uma única chamada. Os itens são processados em ordem e cada um recebe o próprio resultado: mesmo que um falhe, os outros são criados, e o resultado do item mostra qual falhou e por quê.
Embutir objetos relacionados
Se você mandar include=service nos endpoints de pedido, o objeto do serviço vem embutido na resposta e você economiza uma segunda requisição.
Qualidade do serviço e a lista dos melhores serviços
A cada hora o painel mede cada serviço: como terminaram os nossos próprios pedidos (concluídos, cancelados, travados, rejeitados), com que frequência os clientes pediram reposição ou abriram um chamado, quanto tempo a entrega levou de verdade e se a fonte ainda o lista. GET /services/top transforma essas medições em uma lista ranqueada, e include=quality anexa o mesmo relatório a qualquer objeto de serviço.
A pontuação (0-100) é uma combinação ponderada de cinco componentes: confiabilidade (42%, a taxa de sucesso estimada), satisfação (14%, a partir da taxa de reclamações), velocidade (28%, logarítmica no tempo de entrega efetivo; 5 minutos dão pontuação máxima, 48 horas dão zero), a pontuação própria do motor de saúde (8%) e a quantidade de evidências (8%). Pequenos bônus premiam a garantia de reposição, uma fonte confiável e o tempo de catálogo. Serviços em revisão, sinalizados pelo motor de saúde ou vindos de uma fonte em observação são pontuados, mas nunca ranqueados.
Filtre por plataforma, slug de categoria ou prateleira (followers, likes, views... compartilhadas entre plataformas), ordene por score, speed, reliability, price ou orders, e use group_by=category (ou platform) com per_group para receber uma lista por categoria em uma única chamada: exatamente o que uma loja precisa para marcar um serviço 'recomendado' em cada categoria.
# Instagram takipçi kategorisinde en iyi 5 servis
curl "https://panelfollows.com/api/v3/services/top?category=instagram-followers&limit=5" -H "Authorization: Bearer YOUR_API_KEY"
# Her kategori için kanıtlı en iyi 3 servis (tek istek)
curl "https://panelfollows.com/api/v3/services/top?group_by=category&per_group=3&min_confidence=medium" -H "Authorization: Bearer YOUR_API_KEY"| score / grade | 0-100 e A (85+), B (70+), C (55+), D. |
| confidence | none, low, medium, high: quantos pedidos próprios sustentam a pontuação. |
| badges | proven (5+ pedidos, limite inferior de sucesso 60%+), popular (20+ pedidos), fast (entrega em até 1 hora), trusted_source, new (menos de 14 dias). |
| components | reliability, satisfaction, speed, health, evidence; cada um de 0 a 1. |
| evidence.basis | service_orders (pedidos próprios), peer_services (partiu dos outros serviços da fonte) ou none. |
| evidence.delivery_source | measured (nossa mediana em 3+ pedidos concluídos) ou claimed (o tempo anunciado pela fonte, penalizado e limitado). |
| measured_at | Quando o motor de saúde mediu o serviço pela última vez; as pontuações são renovadas a cada hora. |
Referência de endpoints
| Método | Endpoint | Descrição |
|---|---|---|
| GET | /api/v3 | Discovery document: version, endpoints, limits and event types. |
| GET | /api/v3/openapi.json | OpenAPI 3.1 schema for this API. |
| GET | /api/v3/account | Account balance, currency and current rate-limit window. |
| PATCH | /api/v3/account | Set the low balance alert threshold that triggers account.low_balance. |
| GET | /api/v3/services | List services with filters and cursor pagination. |
| GET | /api/v3/services/top | Best services ranked by the quality score; optionally one shortlist per category or platform. |
| GET | /api/v3/services/{id} | Retrieve one service, including its order field schema. |
| GET | /api/v3/categories | List categories with platform, shelf and active service counts. |
| GET | /api/v3/platforms | List platform keys usable as the ?platform= filter, with counts. |
| POST | /api/v3/orders | Create an order. Supports the Idempotency-Key header. |
| POST | /api/v3/orders/preview | Validate an order and compute its charge without creating it. |
| POST | /api/v3/orders/batch | Create up to 50 orders in one call; each item reports its own result. |
| GET | /api/v3/orders | List your orders, newest first. |
| GET | /api/v3/orders/{id} | Retrieve one order. |
| POST | /api/v3/orders/{id}/cancel | Request cancellation. Only for services whose features.cancel is true. |
| POST | /api/v3/orders/{id}/refill | Request a refill for a completed order. |
| GET | /api/v3/refills | List your refill requests, newest first. |
| GET | /api/v3/refills/{id} | Retrieve one refill; refreshes its status from the provider. |
| GET | /api/v3/events | Read your event stream oldest-first; the polling alternative to webhooks. |
| GET | /api/v3/webhooks | List your webhook endpoints. |
| POST | /api/v3/webhooks | Register a webhook endpoint. The signing secret is returned once. |
| GET | /api/v3/webhooks/{id} | Retrieve one webhook endpoint. |
| PATCH | /api/v3/webhooks/{id} | Update a webhook endpoint's url, events, description or active state. |
| DELETE | /api/v3/webhooks/{id} | Delete a webhook endpoint and its delivery log. |
| POST | /api/v3/webhooks/{id}/test | Send a test event to this endpoint, ignoring its event filter. |
| POST | /api/v3/webhooks/{id}/rotate_secret | Generate a new signing secret. The old one stops working immediately. |
| GET | /api/v3/webhooks/{id}/deliveries | Delivery log for one endpoint: attempts, response codes and errors. |
Esquema OpenAPI
Uma definição legível por máquina de todos os endpoints. Passe esse arquivo para um gerador de clientes (openapi-generator, Kiota) ou para o Postman e você recebe um cliente pronto na sua própria linguagem.
https://panelfollows.com/api/v3/openapi.jsonPerguntas frequentes
Minha chave legacy funciona na v3?
Sim. Você não precisa gerar uma chave nova só para testar. Mesmo assim, migre para uma chave v3 em produção: ela pode ser revogada e não fica guardada em texto puro.
Por que os preços vêm como string?
Números de ponto flutuante perdem casas em valores decimais. Devolver strings e converter para um tipo decimal do seu lado elimina de vez essa classe de diferença de arredondamento.
Por que o campo unit importa?
A maioria dos serviços é cobrada a cada 1000 unidades (per_1000), mas os serviços de pacote são vendidos como item único (per_order) e o preço cobre o pacote inteiro. Integrações que ignoravam essa diferença calculavam o preço dos pacotes 1000 vezes errado.
O pedido foi criado, mas ficou em pending. O que aconteceu?
O repasse para o provedor pode ter atrasado. O seu saldo está reservado e o pedido não se perde; nosso time reenvia automaticamente. O campo processing_delayed marca essa situação.
Todos os serviços têm cancelamento e reposição?
Não. Olhe features.cancel e features.refill no objeto do serviço. Chamar o endpoint em um serviço que não oferece o recurso devolve 400.
Posso usar as duas APIs ao mesmo tempo?
Pode. Mesma conta, mesmo saldo, mesmos pedidos. Um pedido aberto pela v2 pode ser consultado pela v3.
A API clássica de revenda, que virou padrão no setor. Esse é o formato que os softwares de painel prontos esperam.
Endpoint
POST https://panelfollows.com/api/v2
POST https://panelfollows.com/api/v2/trAutenticação
Toda requisição leva o parâmetro key. Mantenha a sua chave em segredo e gere outra na hora se ela vazar.
Formato de requisição e resposta
As requisições são enviadas por POST como formulário (application/x-www-form-urlencoded) e as respostas são JSON. Quando falha, também volta HTTP 200, com { "error": "..." } no corpo.
Também é suportado, ainda que nunca tenha sido documentado: você pode chamar por GET e pode mandar o corpo como application/json.
Limite de requisições
240 requisições por minuto por chave, mais 300 por minuto por IP. As requisições que passarem disso são recusadas com 429.
Ações e parâmetros
| action | Parâmetro | Descrição |
|---|---|---|
| services | key, action | Lista todos os serviços ativos (id, nome, categoria, preço, mín./máx., reposição, cancelamento, entrega gradual). |
| add | key, action, service, link, quantity[, runs, interval, comments, username, posts, min, max] | Cria um pedido. service é o id do serviço no catálogo. Adicione runs e interval para entrega gradual e os campos correspondentes para os tipos especiais. |
| status | key, action, order | orders | Status do pedido. Use order para um só, ou a lista orders separada por vírgulas para vários. |
| balance | key, action | Saldo da conta e moeda. |
| refill | key, action, order | orders | Cria um pedido de reposição, encaminhado direto para o provedor. |
| refill_status | key, action, refill | refills | Consulta o status da reposição. |
| cancel | key, action, orders | Cancela pedidos. Só funciona nos serviços cujo provedor aceita cancelamento. |
Exemplo
curl -X POST https://panelfollows.com/api/v2 \
-d "key=YOUR_API_KEY" \
-d "action=add" \
-d "service=1234" \
-d "link=https://instagram.com/username" \
-d "quantity=1000"
# Yanıt: { "order": 23501 }Respostas em turco
Acrescente /tr ao final do endereço para receber nome do serviço, categoria, status do pedido e mensagens de erro em turco. Os parâmetros, as ações e a estrutura da resposta são idênticos, e a sua chave funciona nos dois endereços. Os campos técnicos (type, refill_status, currency) continuam em inglês por compatibilidade com o padrão.
Migrando para a v3
A migração não é obrigatória. Se você resolver migrar, boa parte da sua lógica de negócio se mantém, porque os nomes dos parâmetros continuam os mesmos; o que muda é o transporte e o jeito de ler os erros.
- 1Tire a chave do campo key no corpo e passe para o cabeçalho Authorization: Bearer.
- 2Chame o caminho do recurso no lugar de action=... (POST /orders em vez de add).
- 3Verifique a falha pelo código de status HTTP e por error.code, e não perguntando "tem um campo error?".
- 4Compare o status do pedido pelo valor de máquina, não pelo texto exibido.
- 5Adicione uma Idempotency-Key ao criar pedidos.
- 6Troque a consulta contínua de status por webhooks.
A chave dá acesso à sua conta inteira. Não compartilhe, não embuta em código do lado do cliente e nunca suba para um repositório público.
Chaves v3
Você pode criar quantas chaves quiser, rotular cada uma e revogá-las individualmente. Do nosso lado fica guardado apenas um resumo criptográfico da chave.
Criar conta gratuitaChave legacy
A chave única usada pela API clássica de revenda (v2). Ela também funciona na v3. Quando você gera outra, a antiga perde a validade na mesma hora.
Segurança
- Guarde a chave em uma variável de ambiente, nunca no código-fonte.
- Não coloque a chave em código que roda no navegador; passe as chamadas pelo seu próprio servidor.
- Crie uma chave separada para cada sistema, assim revogar uma não afeta as outras.
- Se desconfiar de um vazamento, coloque a chave nova em uso primeiro e só depois revogue a antiga.
Quando o status de um pedido muda, mandamos uma notificação assinada para o seu servidor, então você não precisa ficar consultando o status.
Por que webhooks?
A consulta contínua é lenta e ainda por cima desperdiça recursos: perguntar por milhares de pedidos a cada minuto consome todo o seu limite de requisições e mesmo assim você só descobre a mudança minutos depois. Com webhook a mudança chega até você no instante em que acontece.
Configuração
- 1Prepare um endereço https público (endereços locais e de rede interna não são aceitos).
- 2Adicione o endereço abaixo e guarde a chave de assinatura, que aparece uma única vez.
- 3Confira a assinatura do seu lado e responda 2xx.
- 4Use o botão de teste para validar o caminho inteiro, de ponta a ponta.
O que a gente envia
POST /hooks/pf HTTP/1.1
Content-Type: application/json
Webhook-Id: evt_7f910fba7cd042ef9d9069ba5c074fa0
Webhook-Timestamp: 1787261223
Webhook-Signature: t=1787261223,v1=9c1e2b0d5c6a7e91...
{
"object": "event",
"id": "evt_7f910fba7cd042ef9d9069ba5c074fa0",
"type": "order.completed",
"created_at": "2026-08-21T00:27:03.531Z",
"data": {
"previous_status": "in_progress",
"order": {
"object": "order",
"id": 23501,
"status": "completed",
"status_label": "Tamamlandı",
"service": 1234,
"quantity": 1000,
"start_count": 4210,
"remains": 0,
"charge": "1.2340",
"currency": "USD"
}
}
}Conferindo a assinatura
Toda requisição carrega o cabeçalho Webhook-Signature: t é o carimbo de data e hora e v1 é a assinatura. A assinatura é o HMAC-SHA256 da string "<carimbo de data e hora>.<corpo bruto>" calculado com a sua chave secreta.
- 1Separe os valores t e v1 do cabeçalho.
- 2Confira que t não tem mais de 5 minutos, para barrar ataques de repetição.
- 3Calcule o HMAC-SHA256 da string "<t>.<corpo bruto>" com a sua chave secreta.
- 4Compare o resultado com v1 em tempo constante e recuse a requisição se não bater.
Exemplo de conferência
import crypto from "node:crypto";
import express from "express";
const app = express();
// ÖNEMLİ: imza HAM gövde üzerinden hesaplanır. JSON'a çevirip yeniden
// dizeye dönüştürürseniz boşluklar değişir ve imza tutmaz.
app.post("/hooks/pf", express.raw({ type: "application/json" }), (req, res) => {
const raw = req.body.toString("utf8");
const header = req.get("Webhook-Signature") ?? "";
const m = /t=(\d+),v1=([0-9a-f]+)/.exec(header);
if (!m) return res.sendStatus(400);
const [, timestamp, signature] = m;
// Tekrar saldırısına karşı: 5 dakikadan eski damgayı reddet.
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return res.sendStatus(400);
const expected = crypto
.createHmac("sha256", process.env.WEBHOOK_SECRET)
.update(`${timestamp}.${raw}`, "utf8")
.digest("hex");
const ok =
expected.length === signature.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
if (!ok) return res.sendStatus(401);
const event = JSON.parse(raw);
// 2xx dönmezseniz gönderim artan aralıklarla tekrar denenir.
res.sendStatus(200);
if (event.type === "order.completed") {
// ... siparişi kendi sisteminizde tamamlandı olarak işaretleyin
}
});Novas tentativas
A primeira tentativa acontece no instante do evento. Se a resposta não for 2xx, ou se a conexão não se estabelecer, o envio é repetido depois de 1 minuto, 5 minutos, 30 minutos, 2 horas e 6 horas. Depois de 6 tentativas no total, o envio é marcado como falho e aparece no log de entregas.
Tipos de evento
Você pode assinar só os tipos que interessam ou receber todos. Uma mudança de status gera exatamente um evento, com o tipo que melhor combina com o status novo.
| order.created | O pedido foi criado. |
| order.processing | O provedor começou a trabalhar no pedido. |
| order.completed | O pedido foi concluído. |
| order.partial | O pedido foi entregue em parte e o restante foi estornado. |
| order.canceled | O pedido foi cancelado ou estornado. |
| order.updated | O status mudou de alguma outra forma. |
| refill.created | Foi aberto um pedido de reposição. |
| refill.updated | O status da reposição mudou. |
| account.low_balance | Seu saldo caiu abaixo do limite que você definiu com PATCH /account. É emitido na travessia, não a cada pedido, e rearma quando o saldo volta a ficar acima dele. |
Se você não puder hospedar um webhook
Os mesmos eventos podem ser lidos por cursor em GET /api/v3/events. Use esse caminho quando estiver desenvolvendo localmente, quando não tiver IP fixo ou quando estiver atrás de um firewall.
// Webhook kuramıyorsanız (yerelde geliştirme, sabit IP yok) aynı bilgiyi
// imleçle çekebilirsiniz. İmleci kendi tarafınızda saklayın.
let cursor = loadCursor(); // en son işlediğiniz olayın "cursor" değeri
const url = new URL("https://panelfollows.com/api/v3/events");
url.searchParams.set("limit", "100");
if (cursor) url.searchParams.set("starting_after", String(cursor));
const res = await fetch(url, { headers: { Authorization: "Bearer YOUR_API_KEY" } });
const { data, has_more } = await res.json();
for (const event of data) {
handle(event); // sizin işleyiciniz
cursor = event.cursor; // imleci ilerlet
}
saveCursor(cursor);Erros (48)
| Código | Status | Descrição |
|---|---|---|
| missing_api_key | 401 | Nenhuma chave de API foi enviada. Envie em 'Authorization: Bearer <key>'. |
| invalid_api_key | 401 | A chave de API que você enviou não é válida. |
| revoked_api_key | 401 | Esta chave de API foi revogada e não pode mais ser usada. |
| account_banned | 403 | Esta conta está banida. |
| account_suspended | 403 | Esta conta está suspensa. |
| insufficient_scope | 403 | Esta chave de API não tem permissão para este endpoint. |
| invalid_json | 400 | O corpo da requisição não é um JSON válido. |
| unsupported_content_type | 415 | Content-Type não suportado. Use application/json ou application/x-www-form-urlencoded. |
| method_not_allowed | 405 | Este método HTTP não é permitido neste endpoint. |
| payload_too_large | 413 | O corpo da requisição é grande demais. |
| missing_parameter | 400 | Um parâmetro obrigatório está faltando. |
| invalid_parameter | 400 | Um parâmetro tem um valor inválido. |
| invalid_link | 400 | O link está faltando ou não é uma URL http(s) válida. |
| invalid_quantity | 400 | A quantidade não é um número inteiro positivo válido. |
| quantity_out_of_range | 400 | A quantidade está fora da faixa permitida por este serviço. |
| invalid_comments | 400 | O campo de comentários está vazio ou tem linhas demais. |
| invalid_username | 400 | O nome de usuário não é válido para este serviço. |
| invalid_subscription | 400 | Os parâmetros da assinatura não são válidos. |
| invalid_runs | 400 | O valor de 'runs' não é válido para o envio gradual. |
| invalid_interval | 400 | O valor de 'interval' não é válido para o envio gradual. |
| dripfeed_not_supported | 400 | Este serviço não suporta envio gradual. |
| missing_required_field | 400 | Um campo exigido por este tipo de serviço está faltando ou é inválido. |
| service_inactive | 400 | Este serviço não está disponível para pedidos no momento. |
| invalid_cursor | 400 | O cursor de paginação não é válido. |
| invalid_limit | 400 | O parâmetro 'limit' está fora da faixa permitida. |
| invalid_webhook_url | 400 | A URL do webhook precisa ser um endereço https:// público. |
| invalid_events | 400 | Um ou mais tipos de evento solicitados são desconhecidos. |
| batch_too_large | 400 | Itens demais em uma única requisição em lote. |
| cancel_not_supported | 400 | Este serviço não suporta cancelamento. |
| refill_not_supported | 400 | Este serviço não oferece reposição. |
| unknown_endpoint | 404 | Endpoint desconhecido. As rotas disponíveis estão na referência da API. |
| service_not_found | 404 | Não existe nenhum serviço com este id. |
| order_not_found | 404 | Não existe nenhum pedido com este id na sua conta. |
| refill_not_found | 404 | Não existe nenhuma reposição com este id na sua conta. |
| webhook_not_found | 404 | Não existe nenhum endpoint de webhook com este id na sua conta. |
| order_not_cancelable | 409 | Este pedido não pode mais ser cancelado por causa do status atual. |
| cancel_rejected | 409 | O fornecedor recusou a solicitação de cancelamento. |
| order_not_completed | 409 | A reposição só pode ser solicitada para um pedido concluído. |
| duplicate_link | 409 | Já existe um pedido ativo para este link. Aguarde a conclusão dele. |
| idempotency_key_reuse | 409 | Esta Idempotency-Key já foi usada com outro corpo de requisição. |
| idempotency_in_progress | 409 | Ainda estamos processando a requisição com esta Idempotency-Key. Tente em breve. |
| webhook_limit_reached | 409 | Você atingiu o número máximo de endpoints de webhook. |
| insufficient_balance | 402 | Seu saldo não é suficiente para este pedido. |
| rate_limit_exceeded | 429 | Limite de requisições excedido. Consulte o cabeçalho de resposta Retry-After. |
| provider_error | 503 | O fornecedor retornou um erro. Tente de novo. |
| refill_failed | 409 | A solicitação de reposição foi recusada pelo fornecedor. |
| service_temporarily_unavailable | 503 | Este serviço está temporariamente indisponível. Tente de novo mais tarde. |
| internal_error | 500 | Ocorreu um erro inesperado do nosso lado. |