EngageGate API
The EngageGate API lets you order social engagement services programmatically. It follows the widely-used SMM-panel V2 protocol, so if you already integrate with other panels the request/response shape will be familiar.
Status: All catalog services are live and orderable — Views, engagement (likes / retweets / bookmarks), and Subscription packages. See Service catalog.
1. Overview
| Endpoint | POST https://engagegate.app/api/v2 |
| Method | POST only |
| Content-Type | application/x-www-form-urlencoded (recommended). application/json is also accepted. |
| Authentication | Your API key, sent either as the key body field or the X-API-Key header. |
| Action | Every request carries an action field selecting the operation (services, balance, topup, add, status, cancel). |
| Responses | Always HTTP 200, even for errors. The body is JSON. |
| Errors | Returned in the body as {"error": "..."}. Never as a non-200 status code. |
Because the API always returns HTTP 200, do not branch on the HTTP status
code to detect failures. Instead, inspect the JSON body: if it contains an
error key, the request failed and the error value is a human-readable
message.
The services action is public — it requires no API key and is not
rate-limited — so you can inspect the catalog before signing up. Every other
action requires a valid API key.
Request shape
POST /api/v2
Content-Type: application/x-www-form-urlencoded
key=YOUR_API_KEY&action=balance
Error envelope
{ "error": "Incorrect API key" }
2. Authentication & keys
- Sign in to your EngageGate account and open
engagegate.app/account/api. - Mint a new API key. The raw key value is shown exactly once — on creation and on regeneration. Copy and store it securely; it cannot be retrieved again. If you lose it, regenerate the key (which invalidates the old value).
- Send the key with every authenticated request, either as:
- the
keybody field, or - the
X-API-KeyHTTP header (this takes precedence if both are supplied).
- the
Any authentication failure — missing key, unknown key, disabled key, or a disabled account — returns the same generic message so the response cannot be used to probe which keys exist:
{ "error": "Incorrect API key" }
Sandbox keys (testing)
When minting a key you can flag it as a sandbox key. Sandbox keys behave
identically to live keys for every read action, but the add action does not
charge your wallet and does not place a real order — it returns a mock,
already-completed order so you can build and test your integration end-to-end
without spending funds or generating real engagement. See the
FAQ for the full sandbox behaviour.
3. Actions
Each action below lists its parameters, a curl example, a Python
(requests) example, and an example JSON
response.
In the Python examples we use form data (data=...), which is the recommended
encoding.
services — list the catalog (public)
Returns the full service catalog as a JSON array. No API key is required and this action is not rate-limited.
Parameters
| Name | Required | Description |
|---|---|---|
action |
yes | services |
curl
curl -s https://engagegate.app/api/v2 \
-d action=services
Python
import requests
resp = requests.post(
"https://engagegate.app/api/v2",
data={"action": "services"},
)
print(resp.json())
Example response (array of service objects)
[
{
"service": 100,
"name": "Likes — Standard",
"type": "Default",
"category": "Likes",
"min": 10,
"max": 1000,
"refill": false,
"cancel": true,
"dripfeed": true,
"rate": "10.00"
},
{
"service": 200,
"name": "Views",
"type": "Default",
"category": "Views",
"min": 100,
"max": 1000000,
"refill": false,
"cancel": true,
"dripfeed": true,
"rate": "0.18"
},
{
"service": 300,
"name": "Subscription Starter",
"type": "Package",
"category": "Subscription",
"min": 1,
"max": 1,
"refill": false,
"cancel": false,
"dripfeed": false,
"flat_price": "359.00"
}
]
Field notes
service— the integer service id you pass toaddand other actions.rate— price per 1,000 units (string, USD) for per-1000 services (Likes, Retweets, Bookmarks, Views).flat_price— a single fixed price (string, USD) forPackageservices (Subscriptions). These rows carryflat_priceinstead ofrate.min/max— the allowed quantity range.refillis alwaysfalse— refill is not supported (seerefill).- The
rateshown for Views is dynamic and may change; always read it fresh fromservicesbefore ordering.
balance — check your wallet balance
Parameters
| Name | Required | Description |
|---|---|---|
key |
yes | Your API key (or send X-API-Key). |
action |
yes | balance |
curl
curl -s https://engagegate.app/api/v2 \
-d key=YOUR_API_KEY \
-d action=balance
Python
import requests
resp = requests.post(
"https://engagegate.app/api/v2",
data={"key": "YOUR_API_KEY", "action": "balance"},
)
print(resp.json())
Example response
{ "balance": "123.45", "currency": "USD" }
balance is a string with two decimals. A new account with no wallet yet simply
reports "0.00" — that is not an error.
topup — add funds to your wallet
Creates a crypto deposit invoice. Pay the invoice and your wallet is credited automatically once payment is confirmed; you do not need to call back.
Parameters
| Name | Required | Description |
|---|---|---|
key |
yes | Your API key (or send X-API-Key). |
action |
yes | topup |
amount |
yes | USD amount to deposit. Must be a number greater than 0. |
curl
curl -s https://engagegate.app/api/v2 \
-d key=YOUR_API_KEY \
-d action=topup \
-d amount=50
Python
import requests
resp = requests.post(
"https://engagegate.app/api/v2",
data={"key": "YOUR_API_KEY", "action": "topup", "amount": "50"},
)
print(resp.json())
Example response
{
"invoice_url": "https://pay.example.com/invoice/abc123",
"invoice_id": "abc123"
}
Open invoice_url to complete payment. On an invalid amount the response is
{"error": "Invalid amount"}; if invoicing is briefly unavailable it is
{"error": "Top-up temporarily unavailable"}.
add — place an order
Places a new order. All catalog services are orderable. Ordering a service that
has been deactivated returns {"error": "Service not available"}; an unknown
service id returns {"error": "Service not found"}.
Parameters
| Name | Required | Description |
|---|---|---|
key |
yes | Your API key (or send X-API-Key). |
action |
yes | add |
service |
yes | The integer service id (e.g. 200 for Views). |
link |
yes | The target URL (e.g. the tweet/post URL). |
quantity |
yes | Number of units to deliver, within the service's min/max. |
Idempotency
Send an optional Idempotency-Key HTTP header (any unique string you
generate per order). If you retry a request with the same key, the original
order is returned instead of creating — and charging — a second order. This
makes safe retries straightforward.
curl
curl -s https://engagegate.app/api/v2 \
-H "Idempotency-Key: my-unique-order-001" \
-d key=YOUR_API_KEY \
-d action=add \
-d service=200 \
-d link=https://x.com/someuser/status/1234567890 \
-d quantity=5000
Python
import requests
import uuid
resp = requests.post(
"https://engagegate.app/api/v2",
headers={"Idempotency-Key": str(uuid.uuid4())},
data={
"key": "YOUR_API_KEY",
"action": "add",
"service": "200",
"link": "https://x.com/someuser/status/1234567890",
"quantity": "5000",
},
)
print(resp.json())
Example response
{ "order": 10042 }
The order value is an integer order id — pass it to status and cancel.
Common add errors
| Error | Meaning |
|---|---|
{"error":"Invalid service"} |
service was missing or not an integer. |
{"error":"Service not found"} |
No active service with that id. |
{"error":"Service not available"} |
That service is currently deactivated and not orderable. |
{"error":"Missing link"} |
link was empty. |
{"error":"Invalid quantity"} |
quantity was non-numeric or outside min/max. |
{"error":"Not enough funds"} |
Your wallet balance is below the order charge. No charge is made. |
{"error":"Fulfillment temporarily unavailable"} |
The order could not be placed; a refund of the charge is issued to your wallet after review. |
status — check order status
Look up one order or a batch of your own orders. You can only see orders placed with your own API key.
Parameters
| Name | Required | Description |
|---|---|---|
key |
yes | Your API key (or send X-API-Key). |
action |
yes | status |
order |
one of | A single order id. |
orders |
one of | A comma-separated list of order ids (max 100). Takes precedence over order. |
curl (single)
curl -s https://engagegate.app/api/v2 \
-d key=YOUR_API_KEY \
-d action=status \
-d order=3f7c2b9e-1a4d-4f2a-9c1e-8b0d6e2a5f33
Python (single)
import requests
resp = requests.post(
"https://engagegate.app/api/v2",
data={
"key": "YOUR_API_KEY",
"action": "status",
"order": 10042,
},
)
print(resp.json())
Example response (single)
{
"charge": "0.90",
"start_count": "0",
"status": "Completed",
"remains": "0",
"currency": "USD"
}
Batch — pass orders (comma-separated). The response is keyed by order id;
a bad id in the batch yields a per-id error and does not fail the rest:
curl -s https://engagegate.app/api/v2 \
-d key=YOUR_API_KEY \
-d action=status \
-d "orders=id-1,id-2"
{
"id-1": {
"charge": "0.90",
"start_count": "0",
"status": "Completed",
"remains": "0",
"currency": "USD"
},
"id-2": { "error": "Order not found" }
}
See Order status taxonomy for the response fields and status values.
cancel — cancel pending order(s)
Cancels one or more of your own orders that are still Pending. If the order was already charged, the order is cancelled and a refund of the charge is issued to your wallet after review. Orders that have moved past Pending cannot be cancelled.
Parameters
| Name | Required | Description |
|---|---|---|
key |
yes | Your API key (or send X-API-Key). |
action |
yes | cancel |
orders |
yes | A comma-separated list of order ids (max 100). |
curl
curl -s https://engagegate.app/api/v2 \
-d key=YOUR_API_KEY \
-d action=cancel \
-d "orders=id-1,id-2"
Python
import requests
resp = requests.post(
"https://engagegate.app/api/v2",
data={
"key": "YOUR_API_KEY",
"action": "cancel",
"orders": "id-1,id-2",
},
)
print(resp.json())
Example response (a list of per-id results)
[
{ "order": 10042, "cancel": 1 },
{ "order": 10043, "error": "Order cannot be cancelled" }
]
{"order": id, "cancel": 1}— cancelled successfully (a refund of any charge is issued to your wallet after review).{"order": id, "error": "Order cannot be cancelled"}— the order is no longer Pending (already processing or terminal).{"order": id, "error": "Order not found"}— unknown id, or not one of your orders.
A request-level problem (no ids, or more than 100) returns the top-level error
envelope, e.g. {"error": "No orders specified"} or {"error": "Too many orders"}.
refill — not supported
Refill is not supported and will not be added. Both refill and
refill_status actions always return:
{ "error": "Refill not supported" }
Every catalog entry accordingly reports "refill": false.
4. Service catalog
The catalog is returned by the services
action. The 7 services are below. Prices are USD.
| ID | Name | Type | Min | Max | Price | Orderable today? |
|---|---|---|---|---|---|---|
| 100 | Likes — Standard | Default | 10 | 1,000 | $10.00 / 1,000 | Yes (live) |
| 102 | Retweets — Standard | Default | 10 | 1,000 | $20.00 / 1,000 | Yes (live) |
| 104 | Bookmarks — Standard | Default | 10 | 1,000 | $6.00 / 1,000 | Yes (live) |
| 200 | Views | Default | 100 | 1,000,000 | Dynamic / 1,000 | Yes (live) |
| 300 | Subscription Starter | Package | 1 | 1 | Flat (monthly) | Yes (live) |
| 301 | Subscription Growth | Package | 1 | 1 | Flat (monthly) | Yes (live) |
| 302 | Subscription Scale | Package | 1 | 1 | Flat (monthly) | Yes (live) |
What's orderable today
All catalog services are live and accepted by the add action:
- Views (200) — up to 1,000,000 per order.
- Engagement — Likes (100), Retweets (102), Bookmarks (104) — 10–1,000 units per order.
- Subscription packages — Starter (300), Growth (301), Scale (302) — placed
with
target_account+billing_periodinstead oflink+quantity.
Placing an add for a service id that does not exist returns
{"error": "Service not found"}.
Pricing notes
- For per-1,000 services (Likes, Retweets, Bookmarks, Views), the catalog
reports
rate(price per 1,000) and the order charge scales linearly with quantity. - Views pricing is dynamic — the
ratefor service200is computed at request time and can change. Always read the currentratefromservicesbefore placing a Views order rather than hard-coding a value. (The figure in theservicesexample above is illustrative only.) - For Subscription packages, the catalog reports a single
flat_price(the monthly price), andmin/maxare both1. The current price for each package is always theflat_pricereturned by theservicesaction.
5. Order status taxonomy
The status field in a status response is one of:
| Status | Meaning |
|---|---|
Pending |
Accepted and queued; not yet started. Cancellable. |
Processing |
Being set up for delivery. |
In progress |
Actively delivering. |
Completed |
Delivered in full. |
Partial |
Delivered in part; the undelivered portion is reflected in remains. |
Canceled |
Cancelled or terminated; any charge is refunded to your wallet after review. |
A single status lookup returns this envelope:
| Field | Type | Description |
|---|---|---|
charge |
string | The amount charged for the order (USD). |
start_count |
string | The metric count at the moment delivery began (0 until known). |
status |
string | One of the values above. |
remains |
string | Units still to be delivered (quantity − delivered). |
currency |
string | Always "USD". |
{
"charge": "0.90",
"start_count": "0",
"status": "In progress",
"remains": "1200",
"currency": "USD"
}
6. Rate limits
- The default limit is 60 requests per minute, per API key.
- The public
servicesaction is not rate-limited. - Every authenticated response includes these headers:
X-RateLimit-Limit— your per-minute limit.X-RateLimit-Remaining— requests left in the current minute window.
- When you exceed the limit, the response (still HTTP 200) is:
{ "error": "Rate limit exceeded" }
Back off and retry in the next minute window. Use the Idempotency-Key header
on add so retries after a rate-limit hit cannot double-charge you.
7. FAQ
What is a Partial order?
A Partial order is one where only some of the requested quantity could be
delivered. The remains field tells you how many units were not delivered. When
delivery falls short, a refund for the undelivered portion is issued to your
wallet after review.
When can I cancel an order?
Only while it is Pending. Once an order moves to Processing (or later), it
can no longer be cancelled, and cancel returns
{"order": id, "error": "Order cannot be cancelled"}. Cancelling a Pending
order that was already charged issues a refund to your wallet after review.
How do I test my integration?
Mint a sandbox API key on engagegate.app/account/api. With a sandbox key,
read actions (balance, status, services) behave normally, and add
returns a mock order that is immediately Completed — no wallet charge and no
real engagement. This lets you exercise the full request/response flow safely.
Is my balance refunded if an order fails?
Yes. If you have funds but fulfillment fails after the charge, the order is
marked failed and a refund of the charge is issued to your wallet after review,
and add returns {"error": "Fulfillment temporarily unavailable"}. Refunds are
reviewed before the credit is applied, so your balance updates once that review
completes. If you simply lack the funds, no charge is made at all and you get
{"error": "Not enough funds"}.
What happens if fulfillment fails?
EngageGate marks the order failed and a refund of the charge is issued to your
wallet after review. You can safely retry (use an Idempotency-Key to make
retries safe).
Why do all responses return HTTP 200?
That is the SMM-panel V2 convention this API follows. Detect failures by
checking for an error key in the JSON body, not by the HTTP status code.
Can I send JSON instead of form data?
Yes — set Content-Type: application/json and send the same fields as a JSON
object. Form-encoded (application/x-www-form-urlencoded) is recommended and is
the protocol default.