notpanel
ServicesPricingFAQGiveawayAPI
notpanel

Followers, likes and views for every platform.

The catalog combines directly operated services with capacity from vetted partners. Current availability, timing, refill, and drip-feed support are shown per service; routing and partner identities remain confidential.

Product

  • Services
  • Pricing
  • Price Index
  • Affiliate Program

Resources

  • API
  • Blog
  • FAQ
  • Status

Company

  • About
  • Why NotPanel
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
  • Refund Policy

Languages

  • English
  • Español
  • Português
  • Русский
  • Türkçe
  • العربية
  • हिन्दी
  • Bahasa Indonesia
  • Français
  • 中文

© 2026 NotPanel. All rights reserved.

support@notpanel.com
notpanel
API documentation
+
API documentation

Introduction

  • Overview
  • Getting started
  • Authentication
  • Rate limits
  • Errors

Catalog

  • List services
  • Advanced catalog
  • Service types

Orders

  • Place order
  • Order status
  • Refund quote
  • Refill
  • Cancel

Account

  • Account status
  • Balance

Webhooks

  • Manage webhooks

Reference

  • Changelog
  • SDKs & libraries

Need help?

support@notpanel.com →

Register webhook

Subscribes a public URL to supported events. Each endpoint receives its own HMAC-SHA256 secret, shown once at creation. If it is lost, remove the endpoint and add it again.

POSThttps://notpanel.com/api/v3action=webhook.add
API key requiredRate limited (shared account + IP + action)Body: application/x-www-form-urlencoded
Maximum 5 webhooks per API key. Use a publicly reachable HTTPS URL. Unsafe, private, loopback, or otherwise non-public destinations are rejected.

Parameters

NameTypeDescription
keyRequiredstringYour API key.
actionRequiredstringMust be the literal string "webhook.add".
urlRequiredstring (URL)Public HTTPS endpoint that will receive POSTs. Must be reachable from the public internet.
eventsstring (CSV)Comma-separated subset of the six supported events below. Omit it to subscribe to all six.

Example request

Replace YOUR_API_KEY with the key generated under your dashboard’s API page.

curl -X POST https://notpanel.com/api/v3 \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "key=YOUR_API_KEY&action=webhook.add&url=https://your-server.example.com/notpanel-webhook&events=order.completed,order.refunded"
const res = await fetch("https://notpanel.com/api/v3", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    key: "YOUR_API_KEY",
    action: "webhook.add",
    url: "https://your-server.example.com/notpanel-webhook",
    events: "order.completed,order.refunded",
  }),
});

const data = await res.json();
console.log(data);
import requests

res = requests.post(
  "https://notpanel.com/api/v3",
  data={
    "key": "YOUR_API_KEY",
    "action": "webhook.add",
    "url": "https://your-server.example.com/notpanel-webhook",
    "events": "order.completed,order.refunded",
},
)
print(res.json())
<?php
$body = http_build_query([
    'key' => 'YOUR_API_KEY',
    'action' => 'webhook.add',
    'url' => 'https://your-server.example.com/notpanel-webhook',
    'events' => 'order.completed,order.refunded',
]);

$response = file_get_contents('https://notpanel.com/api/v3', false, stream_context_create([
    'http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/x-www-form-urlencoded\r\n",
        'content' => $body,
        'ignore_errors' => true,
    ],
]));

print_r(json_decode($response, true));

Example response

{
  "webhook_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
  "url": "https://your-server.example.com/notpanel-webhook",
  "secret": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
  "events": [
    "order.completed",
    "order.refunded"
  ]
}

Common errors

StatusBodyCause
400{"error":"Maximum 5 webhook endpoints per API key"}Existing endpoints exhausted the cap. Remove an unused endpoint with action=webhook.remove first.
400{"error":"Webhook URL must be a publicly reachable HTTPS URL"}The URL was not valid HTTPS, could not be parsed, or resolved to a private/loopback IP.
400{"error":"Webhook event is invalid","error_code":"INVALID_WEBHOOK_EVENT"}Event name is not on the allow-list. Re-check spelling — names use the form "order.<status>".

Available events

  • order.completed
  • order.partial
  • order.processing
  • order.in_progress
  • order.refunded
  • order.refill_completed

List webhooks

action=webhook.list returns every endpoint registered under the calling key, including its delivery health (status, failureCount, lastDeliveredAt).

key=YOUR_API_KEY&action=webhook.list
[
  {
    "id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
    "url": "https://your-server.example.com/notpanel-webhook",
    "events": ["order.completed", "order.refunded"],
    "status": "active",
    "failureCount": 0,
    "lastDeliveredAt": "2026-04-30T15:42:11.000Z",
    "createdAt": "2026-04-15T09:01:00.000Z"
  }
]

Remove a webhook

action=webhook.remove with the endpoint UUID removes the endpoint and revokes its signing secret. A delivery already in progress may still arrive; new events will not be queued for it.

key=YOUR_API_KEY&action=webhook.remove&id=3f2504e0-4f89-41d3-9a0c-0305e82c3301

{
  "success": true
}

Delivery payload

Every delivery is a POST with Content-Type: application/json. The body has top-level events, timestamp, and deliveryId fields. The current public batching defaults group for up to 5 seconds and include at most 50 event objects, each with a stable logical id, plus event, timestamp, and data. Queueing or an outage can add delay, so this is not a 5-second delivery promise. Headers include:

  • X-Webhook-Signature — sha256=&lt;hex&gt;, computed over &lt;timestamp&gt;.&lt;exact JSON body bytes&gt;.
  • X-Webhook-Timestamp — the delivery Unix timestamp in seconds.
  • X-Webhook-Delivery-Id — the batch delivery UUID, reused when that same batch is retried. There is no delivery-level event header; read each event from the body.
{
  "events": [
    {
      "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "event": "order.completed",
      "timestamp": 1777534931,
      "data": {
        "order": 7001,
        "orderId": 7001,
        "serviceId": 1,
        "status": "Completed",
        "status_key": "completed",
        "charge": "0.50",
        "startCount": 1234,
        "remains": 0
      }
    }
  ],
  "timestamp": 1777534931,
  "deliveryId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}

Verifying signatures

Read X-Webhook-Timestamp and the exact received JSON body bytes. Compute HMAC-SHA256 over &lt;timestamp&gt;.&lt;body bytes&gt; with the endpoint secret, format it as sha256=&lt;hex&gt;, and compare it to X-Webhook-Signature in constant time. A retry keeps its event IDs and deliveryId but receives a new timestamp, body, and signature.

As your own replay policy, you may reject a correctly signed delivery when its timestamp differs from your server clock by more than 5 minutes.

Delivery behavior & retries

  • Best-effort with retries. A 2xx response completes a delivery. Each attempt times out after 30 seconds. Failures may be retried starting after 5 seconds with exponential backoff capped at 5 minutes, but delivery is not a durable at-least-once guarantee.
  • Pause threshold. The endpoint is paused after 10 consecutive failed attempts. There is no enable or update action; remove it, then register a replacement with action=webhook.add and store the newly shown secret.
  • Order is not guaranteed. Keep handlers idempotent, process every event in a batch, deduplicate a logical transition by event id or a retried batch by deliveryId, and reconcile important state with action=status.