Like3s API — two standards, one platform.
Integrate Like3s into your system the way that fits best. v1 is a modern REST API; v2 follows the SMM Panel standard — migrating from another panel only takes a URL change.
Introductionv1
Like3s API v1 is a modern REST API — JSON, Bearer API key, meaningful HTTP status codes. Ideal for new projects, mobile apps, or long-term integrations. It returns VND by default; send the header Accept-Currency: USD to receive USD (converted at the live rate).
Base URL
api.like3s.vn
HTTPS required · TLS 1.2+
Prefix
/api/v1
REST · JSON · UTF-8
Rate limit
120 / min
20,000 / day per API key
Pagination
Cursor-based
Orders & transactions
Authentication
Every request must include a Bearer API key in the Authorization header. Keys are created in Dashboard → API Keys; each key is tied to one account and can be restricted by IP and scope.
Authorization: Bearer 3kQp7xN2hVfL8mYwB1tRzAcEgUjK5sDoXrM4nPiF
Content-Type: application/json
Accept: application/json
Accept-Currency: VND // optional · VND | USD · default VND
Idempotency-Key: a8d3f1e2-b4c5-6789-0123-456789abcdef // optional for POST /orders
// REQUIRED for POST /orders/bulk and /orders/{id}/refillCurrency & conversion
By default, every money field (balance, rate, charge, refunded) is returned in VND. Send the header Accept-Currency: USD to receive USD — the backend converts from VND at the internal rate (updated every 4 hours).
GET /api/v1/account/balance
Accept-Currency: USD
// → { "balance": 51.2345, "currency": "USD" }
GET /api/v1/account/balance
// (no header)
// → { "balance": 1286420, "currency": "VND" }currency field is always present in the response — check it instead of assuming the unit.Errors & HTTP status
v1 uses standard HTTP status codes. The error body always has the shape { code, message }.
| Status | Code | Meaning |
|---|---|---|
| 200 | OK | Request succeeded, the body contains the resource. |
| 400 | INVALID_STATUS · VALIDATION | Malformed body or invalid query parameter. |
| 401 | UNAUTHORIZED | API key missing / invalid / revoked. |
| 402 | INSUFFICIENT_BALANCE | Wallet balance is not enough to hold the order amount. |
| 404 | NOT_FOUND | Order / service / variant does not exist or does not belong to the account. |
| 409 | IDEMPOTENCY_CONFLICT | The Idempotency-Key was already used for a different request. |
| 422 | SERVICE_UNAVAILABLE | Service is temporarily paused — retry later or pick an equivalent variant. |
| 429 | RATE_LIMITED | Rate limit exceeded. Read the Retry-After header. |
| 500 | INTERNAL_ERROR | Server error. Logged & alerted to on-call. |
{
"code": "INSUFFICIENT_BALANCE",
"message": "Wallet balance is 12,400 ₫ — the order requires 95,000 ₫."
}Rate limit
Each API key is limited to 120 requests / minute and 20,000 requests / day. Reseller accounts can request a higher limit. When you exceed the limit, the server returns 429 Too Many Requests with a Retry-After header.
Every successful response includes the headers below so the client can throttle proactively — no need to guess the remaining quota:
X-RateLimit-Limit: 120 // max quota in the 1-minute window
X-RateLimit-Remaining: 118 // remaining in the current window
X-RateLimit-Reset: 1747387260 // epoch seconds until the next windowX-RateLimit-Remaining as it nears 0 and pause until X-RateLimit-Reset — far cheaper than getting a 429 and retrying.List platforms
Returns all available platforms (Facebook, Instagram, TikTok, YouTube, Twitter, Shopee...). Use it to build a picker menu or a client-side filter.
/api/v1/platformsRequest
curl "https://api.like3s.vn/api/v1/platforms" \
-H "Authorization: Bearer 3kQp7xN2hVfL8mYwB1tRzAcEgUjK5sDoXrM4nPiF"Response
[
{
"id": 1,
"code": "FACEBOOK",
"slug": "facebook",
"name": "Facebook",
"iconUrl": "https://cdn.like3s.vn/platforms/facebook.svg"
},
{
"id": 2,
"code": "INSTAGRAM",
"slug": "instagram",
"name": "Instagram",
"iconUrl": "https://cdn.like3s.vn/platforms/instagram.svg"
}
// ...
]List services
Returns every available "service" — each service corresponds to one orderable variant. The id field is exactly the value you pass as service when creating an order.
/api/v1/servicesRequest
curl "https://api.like3s.vn/api/v1/services" \
-H "Authorization: Bearer 3kQp7xN2hVfL8mYwB1tRzAcEgUjK5sDoXrM4nPiF"Response
[
{
"id": 103, // variantId · used as "service" in POST /orders
"packageId": 27,
"name": "FB post likes — Basic package",
"type": "DEFAULT", // service-type
"category": "Basic package", // package name
"rate": 21000, // price per 1000 units
"min": 100,
"max": 50000,
"refill": true,
"currency": "VND"
}
// ...
]| Field | Type | Required | Description |
|---|---|---|---|
id | integer | No | Variant ID. Used as service in POST /orders. |
packageId | integer | No | The package this variant belongs to (several variants can share one package). |
name | string | No | Display name (combines packageName + variantLabel). |
type | string | No | Service-type: DEFAULT, MINUTES, REACTIONS_SINGLE, SUBSCRIPTION, ... |
category | string | No | Package name — groups variants together in the UI. |
rate | number | No | Price per 1000 units, in the requested currency. |
min / max | integer | No | The allowed quantity range. |
refill | boolean | No | Whether the service supports refills (auto-monitored for 30 days). |
currency | string | No | VND by default, or USD if you send Accept-Currency: USD. |
Service detail
/api/v1/services/{id}Get a single variant by id. The response shape matches the list endpoint. Returns 404 if the variant does not exist / is unavailable.
Service by slug
/api/v1/services/by-slug/{slug}Resolve a service by slug — matching the FE URL /dich-vu/{slug}. Returns the service with all packages and variants nested — enough to render the order form in a single round-trip.
Request
curl "https://api.like3s.vn/api/v1/services/by-slug/tang-like-bai-viet-facebook" \
-H "Authorization: Bearer 3kQp7xN2hVfL8mYwB1tRzAcEgUjK5sDoXrM4nPiF"Response
{
"id": 12,
"slug": "tang-like-bai-viet-facebook",
"name": "Facebook post likes",
"platformCode": "FACEBOOK",
"platformSlug": "facebook",
"descriptionShort": "Real, safe, long-lasting likes.",
"defaultPackageId": 27,
"packages": [
{
"id": 27,
"serviceId": 12,
"name": "Basic package",
"descriptionShort": "Mixed real likes, delivered 100/hour",
"type": "DEFAULT",
"unitLabel": "like",
"allowScheduled": true,
"variants": [
{
"id": 103,
"label": null,
"rate": 21000,
"min": 100,
"max": 50000,
"refill": true,
"cancel": true,
"data": {}
}
]
},
{
"id": 28,
"serviceId": 12,
"name": "Premium package",
"descriptionShort": "100% real likes, held ≥ 30 days",
"type": "DEFAULT",
"unitLabel": "like",
"allowScheduled": true,
"variants": [
{ "id": 104, "label": null, "rate": 49000, "min": 50, "max": 20000, "refill": true, "cancel": true, "data": {} }
]
}
]
}data: {}. MINUTES/REACTIONS_SINGLE have a discriminator inside data (e.g. { "duration_min": 60 }, { "reaction": "LIKE" }) — copy it verbatim into typeData when calling POST /orders.Package by id
/api/v1/packages/{id}Get a single package with its variants nested. Handy when you already saved a packageId earlier (e.g. from /services/by-slug) and want to fetch it again without the slug.
Response
{
"id": 27,
"serviceId": 12,
"name": "Basic package",
"descriptionShort": "Mixed real likes, delivered 100/hour",
"type": "DEFAULT",
"unitLabel": "like",
"allowScheduled": true,
"variants": [
{
"id": 103,
"label": null,
"rate": 21000,
"min": 100,
"max": 50000,
"refill": true,
"cancel": true,
"data": {}
}
]
}Account & balance
Two endpoints to read the account tied to the API key in use — full details or just the balance.
/api/v1/account{
"id": 42,
"email": "user@example.com",
"balance": 1286420, // available balance (holds deducted)
"currency": "VND"
}/api/v1/account/balanceA lightweight version — returns only the available balance.
{
"balance": 1286420,
"currency": "VND"
}balance already excludes the amount held for in-flight orders — this is the money you can actually use to create new orders.Wallet transactions
/api/v1/account/transactionsThe account's wallet transaction history — semantic events (DEPOSIT / SPEND / REFUND / BONUS / ADJUSTMENT), NOT the raw ledger. Each event has a pre-built title + description you can render straight into the UI without parsing reference.
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
cursor | string | No | Opaque cursor from the previous response's nextCursor. Omit / leave empty for the first page. |
limit | integer | No | Items per page. Default 50, max 200. |
Response
{
"items": [
{
"id": 8472,
"code": "TXN-0008472",
"kind": "SPEND",
"status": "SUCCESS",
"amount": -21000,
"balanceAfter": 1265420,
"currency": "VND",
"title": "Order FB post likes — Basic package #48294",
"description": "1,000 likes · 21.00 ₫/like · facebook.com/like3s/posts/123",
"orderId": 48294,
"createdAt": "2026-05-16T10:42:18+07:00"
},
{
"id": 8401,
"code": "TXN-0008401",
"kind": "DEPOSIT",
"status": "SUCCESS",
"amount": 500000,
"balanceAfter": 1286420,
"currency": "VND",
"title": "Wallet top-up",
"description": "Vietcombank · Reference: NAP1234567",
"orderId": null,
"createdAt": "2026-05-15T22:15:03+07:00"
}
],
"nextCursor": "MjAyNi0wNS0xNVQyMjoxNTowMyswNzowMHw4NDAx"
}| Field | Type | Required | Description |
|---|---|---|---|
kind | string | No | DEPOSIT (top-up) · SPEND (order) · REFUND · BONUS · ADJUSTMENT (support adjustment). |
status | string | No | SUCCESS · PENDING · FAILED. Currently always SUCCESS. |
amount | number | No | Transaction amount (signed — negative for debits). In the requested currency. |
balanceAfter | number | No | The available balance after the transaction — matches GET /account/balance. |
title / description | string | No | Pre-built captions — render straight into the UI. |
orderId | integer | null | No | When kind = SPEND | REFUND: the related order id, used to correlate with GET /orders/{id}. |
nextCursor | string | null | No | Pass into ?cursor= for the next page. null = end. |
balanceAfter is always the available balance (already excluding funds held for in-flight orders).Create order
The most important endpoint. Supports Idempotency-Key for safe retries — a duplicate-key request returns the existing order instead of creating a new one.
/api/v1/ordersBody parameters
| Field | Type | Required | Description |
|---|---|---|---|
service | integer | Yes | The variant ID from GET /api/v1/services. |
link | string | Yes | Public URL of the post / channel / video. Max 1000 characters. |
quantity | integer | Yes | The amount to add. Must be within the service's [min, max] range. |
typeData | object | No | Discriminator depending on type: { "reaction": "LIKE" } for REACTIONS_SINGLE, { "duration_min": 60 } for MINUTES. Omit for DEFAULT. |
startTime | string (ISO-8601) | No | Schedule a future start. null = run now. |
Request
curl "https://api.like3s.vn/api/v1/orders" \
-X POST \
-H "Authorization: Bearer 3kQp7xN2hVfL8mYwB1tRzAcEgUjK5sDoXrM4nPiF" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: a8d3f1e2-b4c5-6789-..." \
-d '{
"service": 103,
"link": "https://facebook.com/like3s/posts/123",
"quantity": 1000
}'Response
{
"id": 48294,
"service": 103,
"link": "https://facebook.com/like3s/posts/123",
"quantity": 1000,
"charge": 21000, // VND · held from the wallet
"refunded": 0,
"currency": "VND",
"status": "PENDING",
"startCount": null,
"remains": 1000,
"failureReason": null,
"createdAt": "2026-05-16T10:42:18+07:00"
}Bulk create orders
/api/v1/orders/bulkCreate 1–50 orders at once sharing the same service, quantity, typeData and startTime — only links is a list. Handy when pushing the same service to many posts / channels.
Idempotency-Key is required. Replaying the same key returns the existing batch; calling again with the same key but a different number of links → 409 IDEMPOTENCY_CONFLICT. Creation is atomic: if one link fails (e.g. insufficient balance on the 35th order) the whole batch rolls back — no order is saved.Body parameters
| Field | Type | Required | Description |
|---|---|---|---|
service | integer | Yes | Variant ID — applied to every link. |
links | array<string> | Yes | 1–50 links. Each link max 1000 characters. Duplicate links within the batch → DUPLICATE_LINK. |
quantity | integer | Yes | Quantity applied to every order in the batch. |
typeData | object | No | Service-type discriminator (see POST /orders). Applied to every order. |
startTime | string (ISO-8601) | No | Schedule a start for every order. null = run now. |
Request
curl "https://api.like3s.vn/api/v1/orders/bulk" \
-X POST \
-H "Authorization: Bearer 3kQp7xN2hVfL8mYwB1tRzAcEgUjK5sDoXrM4nPiF" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: batch-2026-05-16-001" \
-d '{
"service": 103,
"links": [
"https://facebook.com/like3s/posts/1",
"https://facebook.com/like3s/posts/2",
"https://facebook.com/like3s/posts/3"
],
"quantity": 500
}'Response
{
"orders": [
{ "id": 48311, "service": 103, "link": "https://facebook.com/like3s/posts/1",
"quantity": 500, "charge": 10500, "refunded": 0, "currency": "VND",
"status": "PENDING", "startCount": null, "remains": 500,
"failureReason": null, "createdAt": "2026-05-16T10:50:02+07:00" },
{ "id": 48312, "service": 103, "link": "https://facebook.com/like3s/posts/2",
"quantity": 500, "charge": 10500, "refunded": 0, "currency": "VND",
"status": "PENDING", "startCount": null, "remains": 500,
"failureReason": null, "createdAt": "2026-05-16T10:50:02+07:00" },
{ "id": 48313, "service": 103, "link": "https://facebook.com/like3s/posts/3",
"quantity": 500, "charge": 10500, "refunded": 0, "currency": "VND",
"status": "PENDING", "startCount": null, "remains": 500,
"failureReason": null, "createdAt": "2026-05-16T10:50:02+07:00" }
],
"totalCharge": 31500,
"currency": "VND"
}orders matches request.links (index ↔ index). After creation, each order is processed independently — one rejected order only marks itself FAILED + auto-refunds; the others are unaffected.List orders
/api/v1/ordersGet the account's orders — cursor pagination to page through long datasets efficiently (orders are partitioned by month, so offsets are expensive). Fixed sort, newest first.
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
cursor | string | No | Opaque cursor from the previous response's nextCursor. Omit for the first page. |
limit | integer | No | Items per page. Default 50, max 200. |
status | string | No | Filter by status (uppercase): PENDING, PROCESSING, IN_PROGRESS, COMPLETED, PARTIAL, CANCELED, FAILED. |
Response
{
"items": [
{
"id": 48294,
"service": 103,
"link": "https://facebook.com/like3s/posts/123",
"quantity": 1000,
"charge": 21000,
"refunded": 0,
"currency": "VND",
"status": "PROCESSING",
"startCount": 128,
"remains": 358,
"failureReason": null,
"createdAt": "2026-05-16T10:42:18+07:00"
}
// ...
],
"nextCursor": "MjAyNi0wNS0xNlQwOToxNTozMCswNzowMHw0ODI2OA"
}nextCursor is an opaque string — don't parse it. Pass it back verbatim into ?cursor= for the next page. When nextCursor is null, you've reached the end.Order detail
/api/v1/orders/{id}Get a single order by id. The response shape matches an item in the list. Returns 404 if the order does not belong to the account.
{
"id": 48294,
"service": 103,
"link": "https://facebook.com/like3s/posts/123",
"quantity": 1000,
"charge": 21000,
"refunded": 0,
"currency": "VND",
"status": "IN_PROGRESS",
"startCount": 128,
"remains": 358,
"failureReason": null,
"createdAt": "2026-05-16T10:42:18+07:00"
}| Field | Type | Required | Description |
|---|---|---|---|
status | string | No | PENDING · PROCESSING · IN_PROGRESS · COMPLETED · PARTIAL · CANCELED · FAILED |
startCount | integer | null | No | The count at the moment processing started (null before it runs). |
remains | integer | No | The amount left to deliver. |
charge | number | No | The amount held/deducted from the wallet (in the requested currency). |
refunded | number | No | The amount refunded to the wallet when the order is PARTIAL / CANCELED / FAILED. |
failureReason | string | null | No | The system reason when the order is FAILED. |
Cancel order
/api/v1/orders/{id}/cancelRequest to cancel an order. The order moves to CANCELED (or PARTIAL if some was already delivered). The undelivered portion is refunded to the wallet.
{
"id": 48294,
"service": 103,
"link": "https://facebook.com/like3s/posts/123",
"quantity": 1000,
"charge": 21000,
"refunded": 18900, // undelivered portion refunded to the wallet
"currency": "VND",
"status": "CANCELED",
"startCount": 128,
"remains": 900,
"failureReason": null,
"createdAt": "2026-05-16T10:42:18+07:00"
}Request refill
/api/v1/orders/{id}/refillRequest a re-run of an order that is COMPLETED or PARTIAL — useful when likes/follows drop after delivery. Only applies to variants with refill: true that are still within the warranty period (snapshotted at order creation).
Idempotency-Key is required. Reusing the same key returns the existing request — safe for client retries. Rate limit is 24h per order: repeated calls for the same order allow only 1 refill request per 24 hours.REFILL_TOO_EARLY.Request
curl "https://api.like3s.vn/api/v1/orders/48294/refill" \
-X POST \
-H "Authorization: Bearer 3kQp7xN2hVfL8mYwB1tRzAcEgUjK5sDoXrM4nPiF" \
-H "Idempotency-Key: refill-48294-001"Response
{
"id": 48294,
"service": 103,
"link": "https://facebook.com/like3s/posts/123",
"quantity": 1000,
"charge": 21000,
"refunded": 0,
"currency": "VND",
"status": "COMPLETED",
"startCount": 128,
"remains": 0,
"failureReason": null,
"createdAt": "2026-05-16T10:42:18+07:00"
}The order status does not change — the refill request is created in parallel; the system processes it asynchronously via a worker. Refills are free within the warranty period (the wallet is not charged).
| Code | Meaning |
|---|---|
| REFILL_NOT_SUPPORTED | The variant does not support refills (refill: false). |
| REFILL_TOO_EARLY | The order has not been completed for 24h — wait and call again. |
| WARRANTY_EXPIRED | The warranty period has ended (snapshotted at order creation). |
| REFILL_IN_PROGRESS | A refill request is already being processed for this order — wait for it to finish. |
| REFILL_RATE_LIMITED | A refill was already requested for this order in the past 24h. |
| INVALID_STATUS | Only applies to COMPLETED or PARTIAL orders. |
Coming soon
The capabilities below are in development — the exact endpoints and shapes may change before GA.
| Feature | Meaning |
|---|---|
| Webhooks (order events) | Subscribe to order.created / processing / progress / completed / partial / failed — requests signed with HMAC-SHA256. Configured via the Dashboard, not the API. |
| Scope-based API keys | Restrict a key by scope (services:read / orders:create / account:read) — keys currently have full account access. |
| Official SDKs | TypeScript, Python, PHP — auto-generated from the OpenAPI spec. |