TEnergy vs Netts: price, speed and API compared
The only competitor with a five-minute product, an orchestrator that batches up to 100 addresses, and a published 50 rps limit.
- Off-peak until 11:00 UTC UTC
- 1h energy 20 SUN
- 65k · 1h 1.30 TRX
If you already run against Netts, the switch is a constructor change: Keep X-API-KEY, drop X-Real-IP, add a timestamp and a signature, and change /apiv2 to /v1. Your webhook check moves from hex to base64. The table below is every difference we can state as a fact, and the section after it is what Netts does that we do not.
Side by side
| Dimension | Netts | TEnergy |
|---|---|---|
| Tiers | 5 minutes and 1 hour (/apiv2/order5m, /apiv2/order1h) | 5m, 1h and 1d today; 3d and 30d in phase 2 |
| Amount range | 61k–650k for 5m, 61k–3M for 1h | 32k–1M for 5m, 32k–5M for 1h — a lower minimum and a higher ceiling |
| Pricing | Periodic time-of-day pricing in SUN | Published seven-window day-part grid, shown in your time zone |
| Auth | X-API-KEY plus an IP whitelist | X-API-KEY with an HMAC signature; the IP allowlist is optional per key |
| Rate limit | 50 rps | Per-key token buckets, separate read and write |
| Batch | Orchestrator, up to 100 addresses | Batch endpoint, up to 100 receivers |
| Webhook signature | sha256=-prefixed hex | base64 HMAC in X-API-SIGN |
| Testnet | None | Nile, on a separate host with separate keys |
| Other products | Energy reclaim, host mode, AML, sub-users | Energy reclaim; AML and sub-users are not phase-1 products |
What Netts does that we do not
- A five-minute product with a real supply behind it, and an orchestrator built for large batches.
- Host mode, AML screening and sub-users, none of which we ship in phase 1.
- A provider directory at /market that ranks in this niche.
Migration in 5 minutes
Install @tenergy/netts-compat, change the constructor, and your call
sites keep working. The block below is the migration guide itself — it is generated from the
compatibility documentation, so it cannot drift from the shim that implements it.
1. npm install @tenergy/netts-compat. 2. Swap the client and add a secret (realIp is still accepted and ignored, so you can leave it in place):
- const netts = new NettsClient({ apiKey: process.env.NETTS_API_KEY,
- realIp: process.env.PUBLIC_IP, baseUrl: 'https://netts.io' });
+ const netts = new NettsCompatClient({ apiKey: process.env.TENERGY_KEY,
+ apiSecret: process.env.TENERGY_SECRET, // new: we sign, Netts did not
+ baseUrl: 'https://api.tenergy.me' });Call sites do not change: netts.order1h({amount, receiveAddress}), then res.detail.code === 10000 and res.detail.data.orderId / .paidTRX / .hash. Raw HTTP: keep X-API-KEY, drop X-Real-IP, add X-API-TIMESTAMP and X-API-SIGN, change the base path from /apiv2 to /v1; the signing recipe is in ../api/openapi.yaml. 3. Fix your webhook signature check — Netts sent hex with a sha256= prefix, we send base64:
- const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(signed).digest('hex');
- const ok = expected === req.headers['x-netts-signature'];
+ const expected = crypto.createHmac('sha256', secret).update(signed).digest('base64');
+ const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers['x-api-sign']));The signed string and the ±5-minute replay window are identical, so the rest of your handler stands; dedup moves from delivery_id to event_id, both opaque keys in a seen set. 4. Rehearse on Nile (https://api-nile.tenergy.me, separate keys) — Netts had no testnet, so run your whole flow there before switching. 5. Take the two free wins: send your own client_order_id (one line: client_order_id: \payout-${invoiceId}\`, so a timed-out order becomes unambiguous — retry verbatim and you either create it or get the existing one back), and handle order.failed` (one branch in your webhook router, then delete the poller).
Behaves differently: 1 a secret is now required and every request is signed, clock within ±5 s. 2 webhook signature is base64, not sha256=-prefixed hex. 3 delegateAddress is empty — verify with tx_hashes against the chain. 4 delivered energy is exactly what you ordered, no silent +50 (set emulateBuffer: true if you assert on it). 5 we never fill above the quoted price — where Netts would reroute a ≥ 300 000 order to a dearer provider and charge more, we fail it; pass max_price_sun to make the ceiling explicit. 6 order ids do not start with 1H/5M (set prefixOrderIds: true if you parse the prefix). 7 subuser_payout is always null, and the /time/*, /aml/*, /withdraw, /reports/* families are not proxied at all.