API
Tudo o que o painel faz está disponível através de duas APIs distintas. Ambas utilizam a mesma conta, o mesmo saldo e o mesmo catálogo; diferem no formato e nas capacidades.
Tudo o que o painel faz está disponível através de duas APIs distintas. Ambas utilizam a mesma conta, o mesmo saldo e o mesmo catálogo; diferem no formato e nas capacidades.
Porquê duas APIs?
A API clássica de revenda (v2) que todo o setor utiliza envia um formulário para um único endpoint e responde sempre HTTP 200. É exatamente este o formato que o software de painel já feito espera, por isso mantém-se tal como está. Quem escreve o seu próprio sistema, esse, esbarrava constantemente nos limites deste formato: os erros não se distinguiam, o catálogo chegava numa só peça e o estado da encomenda tinha de ser consultado sem fim. A v3 foi escrita para esses casos.
Comparação
| Funcionalidade | 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 em caso de falha | Códigos reais (400, 401, 402, 404, 409, 429, 503) |
| Erros | Texto livre | type + code estável + mensagem localizada + param + doc_url |
| Estado da encomenda | Apenas texto localizado | Valor de máquina estável e ainda uma etiqueta de apresentação à parte |
| Descrição do serviço | Não existe | Descrição em 16 idiomas, tempo médio, plataforma, categoria |
| Campos da encomenda | Deduzidos a partir do nome do tipo | Cada serviço publica o seu próprio esquema de campos |
| Unidade de preço | Não indicada (fonte de erros de 1000x nos pacotes) | Indicada explicitamente como per_1000 ou per_order |
| Catálogo | Todos os serviços numa só resposta | Filtros e paginação por cursor |
| Proteção contra duplicados | Não existe | Idempotency-Key |
| Aviso de estado | Sondagem constante | Webhooks assinados ou fluxo de eventos |
| Esquema | Não existe | 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ência por serviço; lista classificada |
Qual devo escolher?
Escolha a API legacy se utiliza software de painel já feito, um bot ou um painel de revenda. A maioria pede-lhe apenas que altere o endereço da API e a chave, e fica a funcionar em minutos.
Escolha a v3 se está a escrever a sua própria aplicação, loja ou automatização. O tratamento de erros, a proteção contra duplicados e as notificações vêm já incluídos, e pode gerar o formulário de encomenda diretamente a partir do esquema do serviço.
Primeiros passos
- 1Crie uma chave de API no separador Chaves.
- 2Obtenha a lista de serviços e veja o id e o esquema de campos do serviço que vai utilizar.
- 3Valide a encomenda primeiro com preview e só depois a crie.
- 4Registe um webhook, ou leia o fluxo de eventos, para acompanhar as mudanças de estado.
Uma API REST desenhada para programadores que constroem o seu próprio sistema: caminhos orientados a recursos, códigos de estado HTTP reais, erros legíveis por máquina e notificações assinadas.
Endereço base
Todos os caminhos são acrescentados a este endereço. A versão vive no caminho: se alguma vez for necessária uma alteração incompatível, é publicado um caminho novo (v4) e este continua a funcionar sem qualquer mexida. A data de publicação do contrato é devolvida no cabeçalho X-Api-Version em cada resposta.
https://panelfollows.com/api/v3Autenticação
Envie a sua chave de API como token Bearer no cabeçalho Authorization. Em alternativa, também é aceite o cabeçalho X-Api-Key.
GET https://panelfollows.com/api/v3/account
Authorization: Bearer pf_live_...A sua chave legacy atual também funciona na v3, por isso pode experimentar já. Em produção utilize uma chave v3: pode ser etiquetada, revogada uma a uma e nunca fica guardada em texto simples.
Arranque rápido
curl https://panelfollows.com/api/v3/services?limit=5 \
-H "Authorization: Bearer YOUR_API_KEY"Idioma
O idioma da resposta escolhe-se com o cabeçalho Accept-Language ou com o parâmetro ?lang=; o parâmetro prevalece sobre o cabeçalho. O nome do serviço, a descrição do serviço, o nome da categoria, a etiqueta de estado da encomenda, as etiquetas dos campos da encomenda e as mensagens de erro chegam todos nesse idioma.
Os valores de máquina não mudam em idioma nenhum: error.code, order.status, service.type e currency são sempre os mesmos. Escreva as suas condições sobre esses valores e mostre o texto ao utilizador.
Accept-Language: tr
# veya
GET https://panelfollows.com/api/v3/services?lang=trFormato de pedido e resposta
O corpo do pedido é JSON (application/json); para ensaios rápidos também se aceita form-urlencoded. As respostas são JSON: um recurso isolado é um objeto simples e as listas chegam num envelope com data, has_more e next_cursor. Cada objeto traz um campo object que diz qual é o seu tipo.
Os montantes são devolvidos como CADEIAS decimais ("1.2340"), não como vírgula flutuante. Converta-os para um tipo decimal do seu lado, para não se perderem cêntimos. A moeda é USD.
As marcas temporais seguem o formato RFC 3339 (2026-08-21T00:24:45.255Z).
Erros
Em caso de falha é devolvido um código de estado HTTP real e o corpo traz um único objeto error. O seu código deve decidir com base em error.code: esse valor é estável e não muda com 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: se vale a pena repetir ou se o erro é seu. |
| code | Valor de máquina estável. Escreva as suas condições sobre este. |
| message | Explicação legível por pessoas, no idioma que escolheu. |
| param | Nome do campo que deu origem ao erro, quando existe. |
| doc_url | Ligação para a secção exata desta documentação. |
| request_id | A única referência a indicar quando contactar o apoio. |
Limite de pedidos
600 pedidos por minuto por chave, mais 900 por minuto por IP. Cada resposta traz RateLimit-Limit, RateLimit-Remaining e RateLimit-Reset, para que possa abrandar antes de bater no limite. Ultrapassá-lo devolve 429 com um cabeçalho Retry-After.
Paginação
As listas são paginadas por cursor. Envie limit para o tamanho da página (500 no máximo) e starting_after com o id do último registo da página anterior. Continue até has_more ser false; next_cursor dá-lhe o cursor já pronto para a chamada seguinte. Um limit fora do intervalo não é cortado em silêncio, devolve erro: o corte silencioso deixa o cliente convencido de que trouxe tudo.
Proteção contra duplicados (Idempotency-Key)
Acrescente ao pedido um cabeçalho Idempotency-Key aleatório ao criar uma encomenda. Se a ligação cair e repetir com a mesma chave, não é aberta uma segunda encomenda: é devolvida de novo a resposta do primeiro pedido, com o cabeçalho Idempotent-Replay: true. Os registos ficam guardados 24 horas.
Enviar a mesma chave com um corpo DIFERENTE devolve 409 idempotency_key_reuse. Isto quer dizer, quase sempre, que a geração de chaves está avariada do lado do cliente. Um pedido que falha não queima a chave: corrija o problema e repita com a mesma.
Criar uma encomenda
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 numa lista fields os campos que pede na encomenda: nome do campo, tipo, se é obrigatório, os seus limites e ainda uma etiqueta com a respetiva descrição no idioma do utilizador. Quando um campo tem determines_quantity a true, a quantidade é calculada a partir do número de linhas nesse 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é-visualização da encomenda (execução em seco)
POST /orders/preview valida a encomenda e calcula o custo SEM a abrir. Pode mostrar o preço ao seu cliente e ver de antemão se o seu saldo chega. Nada é descontado do saldo e o fornecedor não é contactado.
Encomendas em lote
Com POST /orders/batch pode enviar até 50 encomendas numa só chamada. Os itens são processados por ordem e cada um recebe o seu próprio resultado: mesmo que um falhe, os restantes são abertos, e vê no resultado do item qual falhou e porquê.
Incorporar objetos relacionados
Se enviar include=service nos endpoints de encomenda, o objeto do serviço fica incorporado na resposta e poupa-lhe um segundo pedido.
Qualidade do serviço e a lista dos melhores serviços
A cada hora o painel mede cada serviço: como terminaram as nossas próprias encomendas (concluídas, canceladas, presas, rejeitadas), com que frequência os clientes pediram reposição ou abriram um pedido de suporte, quanto tempo a entrega demorou realmente e se a fonte ainda o lista. GET /services/top transforma essas medições numa lista classificada, 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: fiabilidade (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ência (8 %). Pequenos bónus premeiam a garantia de reposição, uma fonte de confiança e a antiguidade no 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 classificados.
Filtre por plataforma, slug de categoria ou prateleira (followers, likes, views... partilhadas entre plataformas), ordene por score, speed, reliability, price ou orders, e use group_by=category (ou platform) com per_group para obter uma lista por categoria numa ú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: quantas encomendas próprias sustentam a pontuação. |
| badges | proven (5+ encomendas, limite inferior de sucesso 60 %+), popular (20+ encomendas), fast (entrega em menos de 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 (encomendas próprias), peer_services (partiu dos outros serviços da fonte) ou none. |
| evidence.delivery_source | measured (a nossa mediana em 3+ encomendas concluídas) 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 renovam-se 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 cada endpoint. Entregue este ficheiro a um gerador de clientes (openapi-generator, Kiota) ou ao Postman e obtém um cliente pronto na sua própria linguagem.
https://panelfollows.com/api/v3/openapi.jsonPerguntas frequentes
A minha chave legacy funciona na v3?
Sim. Não precisa de gerar uma chave nova para experimentar. Ainda assim, passe para uma chave v3 em produção: pode ser revogada e não fica guardada em texto simples.
Porque é que os preços são cadeias de texto?
Os números de vírgula flutuante perdem casas em montantes decimais. Devolver cadeias e convertê-las para um tipo decimal do seu lado elimina por completo essa classe de diferenças de arredondamento.
Porque é que o campo unit é importante?
A maior parte dos serviços é cobrada por 1000 unidades (per_1000), mas os serviços de pacote são vendidos como um único item (per_order) e o preço cobre o pacote inteiro. As integrações que ignoravam esta distinção calculavam o preço dos pacotes com um erro de 1000 vezes.
A encomenda foi aberta mas ficou em pending. O que aconteceu?
A entrega ao fornecedor pode ter-se atrasado. O seu saldo está cativo e a encomenda não se perde; a nossa equipa reenvia-a automaticamente. O campo processing_delayed assinala este estado.
Todos os serviços têm cancelamento e reposição?
Não. Consulte features.cancel e features.refill no objeto do serviço. Chamar o endpoint num serviço que não os suporta devolve 400.
Posso utilizar as duas APIs ao mesmo tempo?
Sim. A mesma conta, o mesmo saldo e as mesmas encomendas. Uma encomenda aberta pela v2 pode ser consultada pela v3.
A API clássica de revenda, padrão em todo o setor. É este o formato que o software de painel já feito espera.
Endpoint
POST https://panelfollows.com/api/v2
POST https://panelfollows.com/api/v2/trAutenticação
Em cada pedido é enviado o parâmetro key. Guarde a sua chave em segredo e renove-a de imediato se houver fuga.
Formato de pedido e resposta
Os pedidos são enviados por POST como formulário (application/x-www-form-urlencoded) e as respostas são JSON. Em caso de falha também é devolvido HTTP 200, com { "error": "..." } no corpo.
Também é suportado, embora nunca tenha sido documentado até hoje: pode chamá-la com GET e pode enviar o corpo como application/json.
Limite de pedidos
240 pedidos por minuto por chave, mais 300 por minuto por IP. Os pedidos em excesso são recusados 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 faseada). |
| add | key, action, service, link, quantity[, runs, interval, comments, username, posts, min, max] | Cria uma encomenda. service é o id do serviço no catálogo. Acrescente runs e interval para entrega faseada e os campos correspondentes para os tipos especiais. |
| status | key, action, order | orders | Estado da encomenda. Use order para uma só, ou uma lista orders separada por vírgulas para várias. |
| balance | key, action | Saldo da conta e moeda. |
| refill | key, action, order | orders | Cria um pedido de reposição, encaminhado diretamente para o fornecedor. |
| refill_status | key, action, refill | refills | Consulta o estado da reposição. |
| cancel | key, action, orders | Cancela encomendas. Só funciona nos serviços cujo fornecedor suporta o 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 fim do endereço para receber os nomes dos serviços, as categorias, os estados das encomendas e as mensagens de erro em turco. Os parâmetros, as ações e a estrutura da resposta são exatamente iguais, e a sua chave funciona nos dois endereços. Os campos técnicos (type, refill_status, currency) ficam em inglês por compatibilidade com o padrão.
Passar para a v3
A mudança não é obrigatória. Se quiser mudar, a maior parte da sua lógica de negócio mantém-se, porque os nomes dos parâmetros não mudam; o que muda é o transporte e a forma de ler os erros.
- 1Passe a chave do campo key no corpo para o cabeçalho Authorization: Bearer.
- 2Chame o caminho do recurso em vez de action=... (POST /orders em vez de add).
- 3Verifique a falha pelo código de estado HTTP e por error.code, e não por "existe um campo error?".
- 4Compare o estado da encomenda com o valor de máquina, não com o texto apresentado.
- 5Acrescente uma Idempotency-Key ao criar encomendas.
- 6Substitua a sondagem de estado por webhooks.
Uma chave dá acesso a toda a sua conta. Não a partilhe, não a incorpore em código do lado do cliente e nunca a envie para repositórios públicos.
Chaves v3
Pode criar tantas chaves quantas precisar, etiquetar cada uma e revogá-las uma a uma. Do nosso lado é guardado apenas um resumo criptográfico da chave.
Criar conta gratuitaChave legacy
A chave única utilizada pela API clássica de revenda (v2). Também funciona na v3. Ao renová-la, a chave antiga fica inválida no instante seguinte.
Segurança
- Guarde a chave numa variável de ambiente, nunca no código-fonte.
- Não ponha a chave em código que corre no navegador; encaminhe os pedidos pelo seu próprio servidor.
- Crie uma chave separada para cada sistema, para que revogar uma não afete as outras.
- Se suspeitar de uma fuga, ponha primeiro a chave nova a funcionar e só depois revogue a antiga.
Quando o estado de uma encomenda muda, enviamos uma notificação assinada para o seu servidor, para que não tenha de andar a consultar o estado.
Porquê webhooks?
A sondagem é ao mesmo tempo lenta e um desperdício: perguntar por milhares de encomendas a cada minuto esgota o seu limite de pedidos e, ainda assim, só fica a saber da mudança minutos depois. Com webhook a mudança chega-lhe no momento em que acontece.
Configuração
- 1Prepare um endereço https público (endereços locais e de rede interna não são aceites).
- 2Acrescente o endereço abaixo e guarde a chave de assinatura, que só é mostrada uma vez.
- 3Verifique a assinatura do seu lado e devolva 2xx.
- 4Use o botão de teste para confirmar o percurso completo, de ponta a ponta.
O pedido que enviamos
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"
}
}
}Verificação da assinatura
Cada pedido traz um cabeçalho Webhook-Signature: t é a marca temporal e v1 é a assinatura. A assinatura é o HMAC-SHA256 da cadeia "<marca temporal>.<corpo em bruto>" calculado com a sua chave secreta.
- 1Extraia do cabeçalho os valores t e v1.
- 2Confirme que t não tem mais de 5 minutos, para travar ataques de repetição.
- 3Calcule o HMAC-SHA256 da cadeia "<t>.<corpo em bruto>" com a sua chave secreta.
- 4Compare o resultado com v1 em tempo constante e recuse o pedido se não coincidir.
Exemplo de verificação
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 é feita no momento do evento. Se a resposta não for 2xx, ou se a ligação não se estabelecer, o envio é repetido ao fim de 1 minuto, 5 minutos, 30 minutos, 2 horas e 6 horas. Ao fim de 6 tentativas no total, o envio é marcado como falhado e aparece no registo de entregas.
Tipos de evento
Pode subscrever apenas os tipos que lhe interessam ou receber todos. Uma mudança de estado gera exatamente um evento, com o tipo que melhor corresponde ao estado novo.
| order.created | A encomenda foi criada. |
| order.processing | O fornecedor começou a trabalhar na encomenda. |
| order.completed | A encomenda está concluída. |
| order.partial | A encomenda foi entregue em parte e o restante foi devolvido. |
| order.canceled | A encomenda foi cancelada ou devolvida. |
| order.updated | O estado mudou de outra forma qualquer. |
| refill.created | Foi criado um pedido de reposição. |
| refill.updated | O estado da reposição mudou. |
| account.low_balance | O teu saldo desceu abaixo do limite que definiste com PATCH /account. É emitido na passagem, não em cada pedido, e volta a armar quando o saldo sobe acima do limite. |
Se não conseguir alojar um webhook
Os mesmos eventos podem ser lidos com cursor em GET /api/v3/events. Use este caminho enquanto desenvolve localmente, quando não tem IP fixo ou quando está atrás de uma 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 | Estado | Descrição |
|---|---|---|
| missing_api_key | 401 | Não foi enviada nenhuma chave de API. Envie-a em 'Authorization: Bearer <key>'. |
| invalid_api_key | 401 | A chave de API que enviou não é válida. |
| revoked_api_key | 401 | Esta chave de API foi revogada e já não pode ser utilizada. |
| 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 do pedido não é JSON válido. |
| unsupported_content_type | 415 | Content-Type não suportado. Utilize 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 do pedido é demasiado grande. |
| missing_parameter | 400 | Falta um parâmetro obrigatório. |
| invalid_parameter | 400 | Um parâmetro tem um valor inválido. |
| invalid_link | 400 | A ligação está em falta ou não é um URL http(s) válido. |
| invalid_quantity | 400 | A quantidade não é um número inteiro positivo válido. |
| quantity_out_of_range | 400 | A quantidade está fora do intervalo permitido por este serviço. |
| invalid_comments | 400 | O campo de comentários está vazio ou tem demasiadas linhas. |
| invalid_username | 400 | O nome de utilizador não é válido para este serviço. |
| invalid_subscription | 400 | Os parâmetros da subscrição não são válidos. |
| invalid_runs | 400 | O valor de 'runs' não é válido para a entrega faseada. |
| invalid_interval | 400 | O valor de 'interval' não é válido para a entrega faseada. |
| dripfeed_not_supported | 400 | Este serviço não suporta entrega faseada. |
| missing_required_field | 400 | Falta um campo exigido por este tipo de serviço ou o valor é inválido. |
| service_inactive | 400 | Este serviço não está disponível para encomendas de momento. |
| invalid_cursor | 400 | O cursor de paginação não é válido. |
| invalid_limit | 400 | O parâmetro 'limit' está fora do intervalo permitido. |
| invalid_webhook_url | 400 | O URL do webhook tem de ser um endereço https:// público. |
| invalid_events | 400 | Um ou mais dos tipos de evento pedidos são desconhecidos. |
| batch_too_large | 400 | Demasiados itens num único pedido 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 constam da referência da API. |
| service_not_found | 404 | Não existe nenhum serviço com este id. |
| order_not_found | 404 | Não existe nenhuma encomenda 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 | Esta encomenda já não pode ser cancelada devido ao seu estado atual. |
| cancel_rejected | 409 | O fornecedor recusou o pedido de cancelamento. |
| order_not_completed | 409 | A reposição só pode ser pedida para uma encomenda concluída. |
| duplicate_link | 409 | Já existe uma encomenda ativa para esta ligação. Aguarde a sua conclusão. |
| idempotency_key_reuse | 409 | Esta Idempotency-Key já foi utilizada com um corpo de pedido diferente. |
| idempotency_in_progress | 409 | Um pedido com esta Idempotency-Key ainda está a ser processado. Tente em breve. |
| webhook_limit_reached | 409 | Atingiu o número máximo de endpoints de webhook. |
| insufficient_balance | 402 | O seu saldo não é suficiente para esta encomenda. |
| rate_limit_exceeded | 429 | Limite de pedidos excedido. Consulte o cabeçalho de resposta Retry-After. |
| provider_error | 503 | O fornecedor devolveu um erro. Tente novamente. |
| refill_failed | 409 | O pedido de reposição foi recusado pelo fornecedor. |
| service_temporarily_unavailable | 503 | Este serviço está temporariamente indisponível. Tente mais tarde. |
| internal_error | 500 | Ocorreu um erro inesperado do nosso lado. |