Webhooks
Your account has one webhook URL, and every event goes to it. Set it in Dashboard → API, or with Configure Webhook.Events
Six events exist today.Envelope
Every delivery has the same three top-level keys.timestamp is the moment we built the event, ISO-8601 in UTC.
Response
order.updated
number
Order ID.
string
energy or bandwidth.string
processing, filled, partial, failed, reclaimed or reclaim_failed. This field is the source of truth — see the warning below.string
The address the resource was delegated to.
number
The ordered amount — energy units, or bandwidth points.
number
Same as
volume. Present so that expected and delivered can be compared without knowing which field means what.number
How much has actually been delegated so far. Equals
volume once the order is filled; on processing and partial it is the sum of the chunks delegated up to now, and 0 on failure.string
Order price in TRX, as a decimal string.
string | null
Transaction that delegated the resource.
string | null
Transaction that took it back, once the rental ends.
string | null
When the resource is scheduled to be reclaimed, ISO-8601, or
null for orders that are not reclaimed on a timer.Response
subscription.transfer
number
Smart Mode subscription this transfer belongs to.
string
The watched address that sent the transfer.
string | null
The label you gave the subscription.
string
The transfer transaction on chain.
number
How many transfers this delegation covered.
number
Energy delegated for them.
string
What was charged for the energy, in TRX.
string | null
Bandwidth charged on top, or
null when none was.string
Your account balance after the charge.
string
When the transfer was processed. Note this is inside
data and is separate from the envelope’s own timestamp.Response
Transfer Package events
The fourpackage.* events go to the account that owns the package. A package bought by invoice without signing in or an API key has no owner and produces no events. Cancelled invoices, refused purchases and purchases held for manual review produce no events either; a held package sends package.activated once it is activated.
Every package.* event carries these fields in data:
number
Package ID — the
id in List Packages.string
The address the package serves.
string
Package status after the event:
active or completed for package.transfer, completed for package.completed, active for package.activated, expired for package.expired.number
Transfers the package was bought with.
number
Transfers left on this package after the change the event reports — an absolute number, not a difference.
remaining can also go down without an event. A multi-transfer package takes one transfer a day as its daily subscription — the first one at activation, which is why a 500-transfer package starts at remaining: 499 — and that charge is not announced. Two transfers from the same address in the same block can report the same remaining. Treat remaining as a hint and List Packages as the source of truth.(package_id, tx_hash) for package.transfer and (event, package_id) for the others: a retry carries the same body, the same timestamp and the same signature.
package.transfer
A transfer from the address was paid from a package. Sent once per package the transfer was charged to — almost always one event per transfer; a transfer that took the last transfer of one package and continued on the next produces one event for each.
string
The transfer transaction on chain.
number
Transfers taken from this package for this transaction. A transfer to an address that holds no USDT needs double energy and counts as
2, which can be split across two packages.status is completed when this transfer used up the package.
Response
package.completed
The package stopped serving transfers.
string
transfer — a transfer used up the package; subscription — the daily charge used it up; manual — support closed the package. After manual, remaining can be above zero, but those transfers can no longer be used.string | null
For
reason: "transfer", the transfer that closed the package; null otherwise.package.transfer of its own: you receive only package.completed with that transfer’s tx_hash.
Response
package.activated
The package became active and its transfers get energy from now on. Sent for every activation — including a purchase from balance, whose response already says active, and an invoice payment, which activates the package shortly after the payment is seen on chain.
string
How the package was paid: exactly
balance, TRX or USDT.Response
package.expired
An invoice for a package was not paid within its 30-minute window. Nothing was charged; buy again to get a new invoice. No extra fields; remaining equals quota_total and is not available to use.
Response
Delivery
- Up to 3 attempts, with pauses of 1 second and then 4 seconds between them. There is no pause after a success and none after the last attempt.
- 10 seconds timeout per attempt.
- We expect any
2xx. Anything else counts as a failed attempt. - Redirects are not followed. A
301/302is a failed attempt, not a hop. - Missed events are not backfilled. When all three attempts fail, that event is gone; reconcile with Get Order or List Packages rather than waiting for a replay.
Verifying the signature
Every request carriesX-Webhook-Signature: sha256=<hex>, an HMAC-SHA256 over the raw request body keyed with your webhook secret.
Two details decide whether your check works:
- Strip the
sha256=prefix before comparing. The header is not a bare hex digest. - Hash the bytes you received, not a re-serialized object. Parsing the JSON and dumping it again changes key order and spacing, and the signature will never match.