storefront VantaTool
Marketplace Services Pricing About Documentation

VantaTool API

A RESTful API to access all marketplace features programmatically — browse accounts, place boost orders, receive OTP codes, and manage your wallet.

key

Authentication required. All endpoints require an API key. Get yours from your Developer Dashboard.

speed

There is currently no rate limit enforced on any endpoint. Be a good citizen anyway — batch and cache where you can.

lock Authentication

Include your API key in every request using one of these methods (checked in this order):

# 1. Recommended: custom header
curl https://vanta.aces-portal.com/api/v1/me \
  -H "X-API-Key: ik_live_YOUR_KEY"

# 2. Bearer token
curl https://vanta.aces-portal.com/api/v1/me \
  -H "Authorization: Bearer ik_live_YOUR_KEY"

# 3. Query parameter (less secure — avoid in production, ends up in logs)
curl "https://vanta.aces-portal.com/api/v1/me?api_key=ik_live_YOUR_KEY"
warning

Keep your API keys secret. Never expose them in frontend JavaScript or public repositories.

Key types

ik_live_*Production key — real transactions, real balance deducted, real provider calls.
ik_test_*Sandbox key — fully simulated, no balance deducted, no provider call made. Works on /api/v1/sandbox/* routes, and also transparently simulates on the 4 live write endpoints (purchase/order/boost-order/sms-order) — see Sandbox.

A note on 404s

Two different 404 shapes exist. If a resource ID doesn't exist in the database at all, Laravel's own route-model-binding returns its default shape: {"message": "No query results for model [...] 999"}. If the resource exists but doesn't belong to you (or is inactive), the app returns its own consistent shape: {"status": "error", "message": "..."}. Don't assume every 404 has a status field.

data_object Response format

All responses return application/json with a top-level status field of "success" or "error".

// Success
{
  "status": "success",
  "data": { ... },
  "meta": {
    "current_page": 1, "last_page": 5,
    "per_page": 20,  "total": 98
  }
}

// Error
{
  "status": "error",
  "message": "Insufficient wallet balance.",
  "errors": { "quantity": ["The quantity field is required."] }
}

Pagination isn't identical everywhere. On /accounts, /orders, /boosts/orders and /sms/orders, meta sits at the top level, a sibling of data. On /wallet, it's nested inside data.meta. Check the response fields table on each endpoint below.

Decimal fields serialize as strings. Any money field backed by a decimal database column (e.g. account price, wallet transaction amount) is returned as a string like "4500.00", not a JSON number — parse it before doing arithmetic. Fields backed by a plain float/computed column (e.g. order total, boost price_ngn) are real numbers. Each response fields table below marks this explicitly.

error HTTP status codes

200OK — Successful GET/listing, or a state-changing action that isn't a creation (check/resend/cancel).
201Created — Order, purchase, or boost/SMS order was created and its status is not failed.
401Unauthorized — Missing, invalid, or inactive API key.
403Forbidden — A live key (ik_live_*) was used on a /sandbox/* route. (The reverse isn't blocked — a sandbox key works fine on live routes; see Sandbox.)
404Not Found — Resource doesn't exist, doesn't belong to you, or (for accounts) is inactive. Two different shapes — see the note above.
409Conflict — You already have a purchase/order/boost/SMS request in flight. Wait a moment and retry.
410Gone — SMS order expired without receiving an OTP (auto-refunded if it was charged).
422Unprocessable — Validation error, insufficient wallet balance, quantity outside the service's min/max, delivery failed (order created with status failed, not charged), or an action not valid for the order's current status.
402Payment Required — Rare: the upstream provider accepted the order but the wallet debit failed afterward. The app auto-cancels the provider order and marks the local order cancelled.
500Server Error — Unexpected failure. Contact support if persistent.
502Bad Gateway — The upstream provider (boost panel or SMSPool) rejected or failed the request.

shopping_bag Accounts

Browse and purchase social media accounts from the marketplace.

GET /api/v1/accounts

List active accounts, paginated.

science Also at /api/v1/sandbox/accounts — this is a read-only endpoint, sandbox key or live key return identical real data.

Query parameters

Field Required Type Description
category Optional string Filter by category slug (exact match), e.g. instagram.
search Optional string Case-insensitive substring match on account name.
per_page Optional integer Items per page. Default 20. Not clamped — very large values are honored as-is.

Sample request

curl https://vanta.aces-portal.com/api/v1/accounts?category=instagram&per_page=10 \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{
  "status": "success",
  "data": [
    {
      "id": 91, "category_id": 3, "source": "local",
      "name": "Instagram — 10K followers, verified niche page",
      "slug": "ig-10k-verified-niche",
      "price": "4500.00", "stock": 4,
      "followers": "10.2K", "engagement": "4.2%",
      "is_active": true,
      "category": { "id": 3, "name": "Instagram", "slug": "instagram" }
    }
  ],
  "meta": { "current_page": 1, "last_page": 8, "per_page": 10, "total": 76 }
}

Response fields

Field Type Description
id integer Account ID.
category_id integer|null FK to categories.id.
source string local (stock held in our DB) or external (fulfilled via a provider).
name / slug / description string Display fields.
price string (decimal) Selling price in NGN, e.g. 4500.00.
base_price / markup_value string (decimal) Cost basis and markup used to derive price. markup_type is fixed or percentage.
stock integer Units available.
min_quantity / max_quantity integer|null Per-order quantity bounds, if set.
followers / engagement / avg_likes string|null Free-form display text (e.g. 10.2K, 4.2%) — not numeric, do not parse as a number.
credentials — (omitted) Never included in list or show responses — stripped server-side before serialization.
category object Full embedded Category object (id, name, slug, icon, sort_order, is_active, products_count not included here).
meta object (top-level) current_page, last_page, per_page, total — all integers.

Other responses

500 Unexpected failure loading accounts.
{"status":"error","message":"Failed to load accounts."}
GET /api/v1/accounts/categories

List active categories with a live product count.

science Live only — no /sandbox/accounts/categories route exists.

Sample request

curl https://vanta.aces-portal.com/api/v1/accounts/categories \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{
  "status": "success",
  "data": [
    { "id": 3, "name": "Instagram", "slug": "instagram", "sort_order": 1, "is_active": true, "products_count": 24 }
  ]
}

Response fields

Field Type Description
id / name / slug integer / string / string Category identity.
sort_order integer Display order.
is_active boolean Always true — inactive categories are excluded.
products_count integer Count of active accounts in this category.

Other responses

500 Unexpected failure loading categories.
{"status":"error","message":"Failed to load categories."}
GET /api/v1/accounts/{id}

Get a single account. credentials is always stripped.

science Also at /api/v1/sandbox/accounts/{id} — identical, read-only.

Sample request

curl https://vanta.aces-portal.com/api/v1/accounts/91 \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{
  "status": "success",
  "data": {
    "id": 91, "category_id": 3, "source": "local",
    "name": "Instagram — 10K followers, verified niche page",
    "price": "4500.00", "stock": 4, "is_active": true,
    "category": { "id": 3, "name": "Instagram" }
  }
}

Other responses

404 Account exists but is inactive (app-level 404).
{"status":"error","message":"Account not found."}
404 No account with that ID exists at all (framework default 404 — no status field).
{"message":"No query results for model [App\\\\Models\\\\Account] 999"}
500 Unexpected failure loading the account.
{"status":"error","message":"Failed to load account."}
POST /api/v1/accounts/{id}/purchase

Buy an account immediately ('buy now').

science Also at /api/v1/sandbox/accounts/{id}/purchase, or just call this same path with an ik_test_* key.

Body parameters (JSON)

Field Required Type Description
quantity Optional integer How many units to buy. min 1, max 100. Defaults to 1.

Sample request

curl -X POST https://vanta.aces-portal.com/api/v1/accounts/91/purchase \
  -H "X-API-Key: ik_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"quantity": 1}'

Success response — 201

{
  "status": "success",
  "message": "Account purchased successfully.",
  "data": {
    "id": 4021, "user_id": 12, "type": "account", "total": 4500,
    "status": "completed", "external_order_id": null,
    "items": [{
      "id": 7710, "product_id": 91, "quantity": 1, "price": "4500.00",
      "credentials_delivered": { "credentials": "username:password" }
    }]
  }
}

Success response — sandbox key (201)

Same endpoint — pass an ik_test_* key instead of ik_live_* to get simulated data. No wallet debit, no real stock/provider call.

{
  "status": "success", "sandbox": true,
  "message": "Sandbox purchase simulated successfully.",
  "data": {
    "order_id": "sandbox_65123abf9c2e1", "account": "Instagram — 10K followers...",
    "quantity": 1, "total": 4500, "status": "completed",
    "credentials": { "sandbox": true, "note": "This is a sandbox order — no real credentials delivered." }
  }
}

Response fields

Field Type Description
data (live) object The raw Order: id, user_id, type, total (number), status, external_order_id, metadata, created_at, updated_at, items[].
data.status string completed on success. If delivery genuinely fails (out of stock / provider error), the API responds 422 instead — see below — you will not see status: failed on a 201.
data.items[].credentials_delivered object The actual login/credential payload delivered to the buyer.

Other responses

422 Validation failed on quantity.
{"status":"error","message":"Validation failed.","errors":{"quantity":["The quantity must be at least 1."]}}
422 Insufficient wallet balance, or the account is unavailable — no order was created.
{"status":"error","message":"Purchase failed. Insufficient balance or account unavailable."}
422 Balance was sufficient and an order was created, but delivery failed (no stock left / provider error). You were not charged.
{"status":"error","message":"Purchase failed. The account could not be delivered \u2014 you were not charged.","data":{"status":"failed","...":"..."}}
500 Unexpected failure.
{"status":"error","message":"Purchase failed."}

rocket_launch Boost services

Place social media growth orders — followers, likes, views, comments — fulfilled by our upstream growth provider.

GET /api/v1/boosts/categories

List service categories with counts, grouped from the provider's live catalog.

science Live only — no /sandbox/boosts/categories route exists.

Sample request

curl https://vanta.aces-portal.com/api/v1/boosts/categories \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "data": [ { "name": "Instagram", "service_count": 48 } ] }

Response fields

Field Type Description
name string Category name, e.g. Instagram.
service_count integer Number of services in that category, right now.

Other responses

500 Provider catalog fetch failed.
{"status":"error","message":"Failed to load categories."}
GET /api/v1/boosts/services

List purchasable services with NGN/USD pricing.

science Also at /api/v1/sandbox/boosts/services — identical, read-only.

Query parameters

Field Required Type Description
category Optional string Case-insensitive substring match on the provider category field.
search Optional string Case-insensitive substring match on service name.
page Optional integer Default 1.
per_page Optional integer Default 50, clamped between 10 and 100.

Sample request

curl https://vanta.aces-portal.com/api/v1/boosts/services?category=instagram \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{
  "status": "success",
  "data": [
    { "service": 123, "name": "Instagram Followers - Real", "category": "Instagram",
      "rate": "27.0000", "min": "100", "max": "50000",
      "price_ngn": 1.35, "price_usd": 0.000818 }
  ],
  "meta": { "current_page": 1, "per_page": 50, "total": 640, "last_page": 13 }
}

Response fields

Field Type Description
service / name / category / rate / min / max / dripfeed / refill / cancel / type provider-defined Passed through verbatim from the upstream provider — exact types (often stringy numbers) are whatever the provider returns, not controlled by this app.
price_ngn number (float) App-computed: rate marked up per our settings, converted to NGN per unit.
price_usd number (float) App-computed: same, in USD.

Other responses

500 Provider catalog fetch failed.
{"status":"error","message":"Failed to load boost services."}
POST /api/v1/boosts/orders

Place a boost order for a specific service and link.

science Also at /api/v1/sandbox/boosts/orders, or call this same path with an ik_test_* key.

Body parameters (JSON)

Field Required Type Description
service_id Required integer The service field from GET /boosts/services.
link Required string (URL) The profile/post URL to grow. Must be a valid URL, max 2048 chars.
quantity Required integer Must fall within that service min/max range (see GET /boosts/services).

Sample request

curl -X POST https://vanta.aces-portal.com/api/v1/boosts/orders \
  -H "X-API-Key: ik_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"service_id": 123, "link": "https://instagram.com/yourhandle", "quantity": 500}'

Success response — 201

{
  "status": "success",
  "message": "Boost order placed successfully.",
  "data": {
    "order_id": 7, "external_order_id": "98201",
    "service_name": "Instagram Followers - Real", "link": "https://instagram.com/yourhandle",
    "quantity": 500, "total": 1350.0, "status": "processing"
  }
}

Success response — sandbox key (201)

Same endpoint — pass an ik_test_* key instead of ik_live_* to get simulated data. No wallet debit, no real stock/provider call.

{
  "status": "success", "sandbox": true,
  "message": "Sandbox boost order simulated.",
  "data": {
    "order_id": "sandbox_boost_65123abf9c2e1", "service_id": 123,
    "quantity": 500, "total_ngn": 1350.0, "status": "processing"
  }
}

Response fields

Field Type Description
order_id integer Local order ID.
external_order_id string The provider order ID (numeric, but returned as a string).
total number (float) Amount charged in NGN.
status string processing immediately after creation.

Other responses

404 service_id does not match any service in the provider current catalog.
{"status":"error","message":"Service not found."}
422 quantity is outside that service min/max range.
{"status":"error","message":"Quantity must be between 100 and 50000."}
422 Insufficient wallet balance — note required/balance sit at the top level, not under data.
{"status":"error","message":"Insufficient wallet balance.","required":1350,"balance":800}
502 The provider rejected or failed to place the order.
{"status":"error","message":"Failed to place boost order with provider."}
402 Rare: provider accepted the order but the wallet debit failed afterward. The provider order is auto-cancelled and the local order is marked cancelled.
{"status":"error","message":"Payment failed."}
409 You already have an order in flight — wait for it to finish.
{"status":"error","message":"Your previous order is still processing. Please wait a moment and try again."}
500 Unexpected failure.
{"status":"error","message":"Failed to place boost order."}
GET /api/v1/boosts/orders

List your boost orders.

science Live only — no /sandbox/boosts/orders route exists.

Query parameters

Field Required Type Description
per_page Optional integer Default 15.

Sample request

curl https://vanta.aces-portal.com/api/v1/boosts/orders \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "data": [ { "id": 7, "type": "boost", "total": 1350.0, "status": "completed" } ], "meta": { "current_page": 1, "last_page": 1, "per_page": 15, "total": 3 } }

Other responses

500 Unexpected failure.
{"status":"error","message":"Failed to load boost orders."}
GET /api/v1/boosts/orders/{id}

Get order status, refreshed live from the provider on every call.

science Live only — no /sandbox/boosts/orders/{id} route exists.

Sample request

curl https://vanta.aces-portal.com/api/v1/boosts/orders/7 \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{
  "status": "success",
  "data": {
    "order_id": 7, "external_order_id": "98201", "quantity": 500,
    "start_count": 10230, "remains": 120, "charge": "13.50",
    "total": 1350.0, "status": "completed"
  }
}

Response fields

Field Type Description
start_count / remains / charge string|null Populated once the provider has status data; null until then.
status string Mapped from the provider: completed → completed, cancelled/refunded → cancelled, anything else → processing.

Other responses

404 Not your order, or not a boost order.
{"status":"error","message":"Order not found."}
500 Unexpected failure.
{"status":"error","message":"Failed to get order status."}

sms SMS verification

Rent a virtual phone number and receive OTP codes for any service — WhatsApp, Telegram, Google, and more — via SMSPool.

GET /api/v1/sms/countries

List available countries.

science Also at /api/v1/sandbox/sms/countries — identical, read-only, cached.

Sample request

curl https://vanta.aces-portal.com/api/v1/sms/countries \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "data": [ { "ID": "1", "name": "United States" } ] }

Other responses

500 Provider fetch failed.
{"status":"error","message":"Failed to load countries."}
GET /api/v1/sms/services

List available apps/services (WhatsApp, Telegram, Google, etc.).

science Also at /api/v1/sandbox/sms/services — identical, read-only, cached.

Sample request

curl https://vanta.aces-portal.com/api/v1/sms/services \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "data": [ { "ID": "542", "name": "WhatsApp" } ] }

Other responses

500 Provider fetch failed.
{"status":"error","message":"Failed to load services."}
GET /api/v1/sms/price

Get the current NGN/USD price for a country + service combination.

science Also at /api/v1/sandbox/sms/price — identical, read-only.

Query parameters

Field Required Type Description
country Required string Country name, matched case-insensitively, e.g. United States.
service Required string Service name, matched case-insensitively, e.g. WhatsApp.
pool Optional string Pin the quote to a specific provider stock pool.

Sample request

curl "https://vanta.aces-portal.com/api/v1/sms/price?country=United+States&service=WhatsApp" \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{
  "status": "success",
  "data": {
    "country": "United States", "service": "WhatsApp",
    "price_usd": 0.45, "price_ngn": 866.25, "exchange_rate": 1550.0
  }
}

Response fields

Field Type Description
price_usd / price_ngn number (float) | null null if the provider has no price for that combination right now (e.g. out of stock).
exchange_rate number (float) USD → NGN rate used for the conversion.

Other responses

422 Missing country or service.
{"status":"error","message":"Validation failed.","errors":{"country":["The country field is required."]}}
404 Dynamic message — country or service name did not match anything.
{"status":"error","message":"Country not found: Wakanda"}
500 Unexpected failure.
{"status":"error","message":"Failed to get price."}
POST /api/v1/sms/orders

Purchase a virtual number for a country + service combination.

science Also at /api/v1/sandbox/sms/orders, or call this same path with an ik_test_* key.

Body parameters (JSON)

Field Required Type Description
country Required string Same matching as GET /sms/price.
service Required string Same matching as GET /sms/price.
pool Optional string Pin to the same pool your price quote used, for price consistency.
areacode Optional string US area code targeting, max 10 chars. Passed through to the provider as-is.

Sample request

curl -X POST https://vanta.aces-portal.com/api/v1/sms/orders \
  -H "X-API-Key: ik_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country": "United States", "service": "WhatsApp"}'

Success response — 201

{
  "status": "success",
  "message": "SMS number purchased. Waiting for the OTP.",
  "data": {
    "order_id": 88, "external_id": "SP9911234", "number": "+15551234567",
    "country": "United States", "service": "WhatsApp",
    "price_ngn": 866.25, "status": "pending",
    "expires_at": "2026-08-09T10:20:00.000000Z"
  }
}

Success response — sandbox key (201)

Same endpoint — pass an ik_test_* key instead of ik_live_* to get simulated data. No wallet debit, no real stock/provider call.

{
  "status": "success", "sandbox": true,
  "message": "Sandbox SMS number simulated.",
  "data": {
    "order_id": "sandbox_sms_65123abf9c2e1", "number": "+15559998877",
    "price_ngn": 866.25, "status": "pending",
    "note": "This is a sandbox order — no real number was purchased."
  }
}

Response fields

Field Type Description
number string The purchased phone number, e.g. +15551234567.
price_ngn number (float) The actual charged price — recomputed from what the provider really billed, can differ slightly from the price quote.
status string pending immediately after creation — poll GET /sms/orders/{id}/check for the OTP.
expires_at string (ISO 8601) When this order auto-expires if no OTP arrives.

Other responses

422 Insufficient wallet balance — required/balance sit at the top level.
{"status":"error","message":"Insufficient wallet balance.","required":866.25,"balance":100}
404 Dynamic message.
{"status":"error","message":"Service not found: Discord"}
502 Dynamic provider message, e.g. no numbers currently available.
{"status":"error","message":"No numbers currently available for this country\/service."}
402 Rare: number was purchased from the provider but the wallet debit failed afterward. Auto-cancelled.
{"status":"error","message":"Payment failed."}
409 You already have an order in flight.
{"status":"error","message":"Your previous order is still processing. Please wait a moment and try again."}
500 Unexpected failure.
{"status":"error","message":"Failed to purchase SMS number."}
GET /api/v1/sms/orders/{id}/check

Poll for the OTP. Repeat until status leaves pending.

science Live only — no /sandbox/sms/orders/{id}/check route exists.

Sample request

curl https://vanta.aces-portal.com/api/v1/sms/orders/88/check \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

// OTP received
{
  "status": "success", "message": "OTP received.",
  "data": { "order_id": 88, "otp_code": "485920", "full_sms": "Your WhatsApp code is 485920", "status": "completed" }
}

// Still pending
{
  "status": "success", "message": "Still waiting for OTP. Please retry shortly.",
  "data": { "order_id": 88, "status": "pending", "expires_at": "..." }
}

Response fields

Field Type Description
otp_code / full_sms string Only present once status is completed.

Other responses

404 Not your order, or not an SMS order.
{"status":"error","message":"Order not found."}
410 Expired with no OTP. Auto-refunded if it was charged (message drops the Refunded. suffix if the order had a zero total).
{"status":"error","message":"Order expired. No OTP was received. Refunded.","data":{"order_id":88,"status":"expired"}}
500 Unexpected failure.
{"status":"error","message":"Failed to check SMS status."}
POST /api/v1/sms/orders/{id}/resend

Ask the provider to resend the SMS to the same number.

science Live only — no sandbox equivalent.

Sample request

curl -X POST https://vanta.aces-portal.com/api/v1/sms/orders/88/resend \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "message": "SMS resend requested.", "data": { "order_id": 88 } }

Other responses

404 Not your order, or not an SMS order.
{"status":"error","message":"Order not found."}
422 Order is no longer pending (already completed, expired, or cancelled).
{"status":"error","message":"Only pending orders can be resent."}
500 Unexpected failure.
{"status":"error","message":"Failed to resend SMS."}
DELETE /api/v1/sms/orders/{id}

Cancel a pending order.

science Live only — no sandbox equivalent.

Sample request

curl -X DELETE https://vanta.aces-portal.com/api/v1/sms/orders/88 \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "message": "Order cancelled.", "data": { "order_id": 88, "status": "cancelled" } }

Other responses

404 Not your order, or not an SMS order.
{"status":"error","message":"Order not found."}
422 Order is no longer pending.
{"status":"error","message":"Only pending orders can be cancelled."}
500 Unexpected failure.
{"status":"error","message":"Failed to cancel order."}
info Manually cancelling here does not refund your wallet — only an order that auto-expires (see /check above) is refunded automatically.
GET /api/v1/sms/orders

List your SMS orders.

science Live only — no sandbox equivalent.

Query parameters

Field Required Type Description
per_page Optional integer Default 15.

Sample request

curl https://vanta.aces-portal.com/api/v1/sms/orders \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "data": [ { "id": 88, "type": "sms", "status": "completed" } ], "meta": { "current_page": 1, "last_page": 2, "per_page": 15, "total": 19 } }

Other responses

500 Unexpected failure.
{"status":"error","message":"Failed to load SMS orders."}

receipt_long Orders

View all your orders across every service type in one place, or place an account order without going through the accounts endpoint.

GET /api/v1/orders

List all your orders, optionally filtered.

science Also at /api/v1/sandbox/orders — identical, read-only.

Query parameters

Field Required Type Description
type Optional string One of account, boost, sms. Any other value (including email, which exists internally but is not filterable here) is silently ignored — you get unfiltered results.
status Optional string One of pending, processing, completed, partial, failed, cancelled, refunded, expired. An unrecognized value just yields an empty result set — it is not validated.
per_page Optional integer Default 15.

Sample request

curl "https://vanta.aces-portal.com/api/v1/orders?type=account&status=completed" \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "data": [ { "id": 4021, "type": "account", "total": 4500, "status": "completed", "items": [ { "..." : "..." } ] } ], "meta": { "current_page": 1, "last_page": 3, "per_page": 15, "total": 34 } }

Other responses

500 Unexpected failure.
{"status":"error","message":"Failed to load orders."}
GET /api/v1/orders/{id}

Get a single order (any type) by ID.

science Live only — no /sandbox/orders/{id} route exists.

Sample request

curl https://vanta.aces-portal.com/api/v1/orders/4021 \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "data": { "id": 4021, "type": "account", "total": 4500, "status": "completed", "items": [ { "..." : "..." } ] } }

Other responses

404 Order exists but is not yours.
{"status":"error","message":"Order not found."}
404 No order with that ID exists at all (framework default 404).
{"message":"No query results for model [App\\\\Models\\\\Order] 999"}
500 Unexpected failure.
{"status":"error","message":"Failed to load order."}
POST /api/v1/orders

Place an account order directly, by account_id instead of via the URL.

science Also at /api/v1/sandbox/orders, or call this same path with an ik_test_* key.

Body parameters (JSON)

Field Required Type Description
account_id Required integer Must reference an existing row in accounts — validated with exists:accounts,id before any purchase logic runs.
quantity Optional integer min 1, max 100. Defaults to 1.

Sample request

curl -X POST https://vanta.aces-portal.com/api/v1/orders \
  -H "X-API-Key: ik_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"account_id": 91, "quantity": 1}'

Success response — 201

{ "status": "success", "message": "Order placed successfully.", "data": { "id": 4022, "type": "account", "total": 4500, "status": "completed" } }

Success response — sandbox key (201)

Same endpoint — pass an ik_test_* key instead of ik_live_* to get simulated data. No wallet debit, no real stock/provider call.

{ "status": "success", "sandbox": true, "message": "Sandbox order simulated.", "data": { "order_id": "sandbox_65123abf9c2e1", "quantity": 1, "total": 4500, "status": "completed" } }

Other responses

422 account_id missing, non-integer, or does not exist.
{"status":"error","message":"Validation failed.","errors":{"account_id":["The selected account id is invalid."]}}
422 Insufficient balance or account unavailable — no order created.
{"status":"error","message":"Insufficient balance or account unavailable."}
422 Order was created but delivery failed. You were not charged.
{"status":"error","message":"Order failed. The account could not be delivered \u2014 you were not charged.","data":{"status":"failed"}}
500 Unexpected failure.
{"status":"error","message":"Failed to place order."}

account_balance_wallet Wallet

Check your balance and transaction history.

GET /api/v1/wallet

Balance plus paginated transaction history.

science Also at /api/v1/sandbox/wallet — identical, key type has no effect on this read-only endpoint.

Query parameters

Field Required Type Description
per_page Optional integer Default 20.

Sample request

curl https://vanta.aces-portal.com/api/v1/wallet?per_page=10 \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{
  "status": "success",
  "data": {
    "balance": 15000.0, "currency": "NGN",
    "transactions": [
      { "id": 501, "type": "debit", "amount": "2500.00", "balance_after": "12500.00", "status": "completed" }
    ],
    "meta": { "current_page": 1, "last_page": 5, "per_page": 10, "total": 47 }
  }
}

Response fields

Field Type Description
balance number (float) Current NGN balance.
transactions[].amount / balance_after string (decimal) e.g. 2500.00 — NOT a JSON number. balance_after can be null on very old rows.
transactions[].type string credit or debit.
transactions[].status string pending, completed, or failed.
meta object (nested in data) Unlike other list endpoints, pagination meta is data.meta, not top-level.

Other responses

500 Unexpected failure.
{"status":"error","message":"Failed to load wallet."}
GET /api/v1/wallet/balance

Just the balance — cheaper than /wallet when you don't need history.

science Also at /api/v1/sandbox/wallet/balance — identical.

Sample request

curl https://vanta.aces-portal.com/api/v1/wallet/balance \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{ "status": "success", "data": { "balance": 15000.0, "currency": "NGN" } }

Other responses

500 Unexpected failure.
{"status":"error","message":"Failed to load balance."}

person Profile

Your account, wallet snapshot, and the API key that authenticated the request.

GET /api/v1/me

Get your profile, wallet snapshot, and key metadata.

science Also at /api/v1/sandbox/me — returns the exact same data either way; sandbox is a flag on the response (data.sandbox), not a different dataset.

Sample request

curl https://vanta.aces-portal.com/api/v1/me \
  -H "X-API-Key: ik_live_YOUR_KEY"

Success response — 200

{
  "status": "success",
  "data": {
    "id": 12, "name": "Jane Doe", "email": "jane@example.com",
    "wallet": { "balance": 15000.0, "currency": "NGN" },
    "api_key": { "type": "live", "request_count": 482, "last_used_at": "2026-08-09T10:15:00.000000Z" },
    "sandbox": false
  }
}

Response fields

Field Type Description
wallet.balance number (float) 0 if you somehow have no wallet row yet.
api_key.type string sandbox or live, from the key that authenticated this request.
api_key.last_used_at string (ISO 8601) | null Reflects the value at the start of the request, before this request own usage-tracking update lands.
sandbox boolean True if the key that authenticated this request is a sandbox key.

Other responses

500 Unexpected failure.
{"status":"error","message":"Failed to load profile."}

science Sandbox

Test your integration safely using an ik_test_* key. No real transactions are made, and your wallet is never touched.

science

Two ways to get sandbox behavior. Either call the dedicated /api/v1/sandbox/* path (which rejects a live key with 403), or simply authenticate with an ik_test_* key on the plain live path for /accounts/{id}/purchase, /orders, /boosts/orders, and /sms/orders — the key type alone decides whether you get simulated or real data on those four.

Endpoints with a dedicated /sandbox/ path

All read-only endpoints below return the same real catalog/wallet data either way — sandbox only changes behavior on the four write endpoints.

/me/wallet/wallet/balance
/accounts/accounts/{id}/accounts/{id}/purchase (simulated)
/orders (list + create)/boosts/services/boosts/orders (create only, simulated)
/sms/countries/sms/services/sms/price
/sms/orders (create only, simulated)

Live-only — no sandbox path exists

Mostly read endpoints scoped to already-created real orders, which can't be meaningfully simulated.

/accounts/categories/orders/{id}/boosts/categories
/boosts/orders (list + status)/sms/orders (list)/sms/orders/{id}/check, /resend, DELETE

Sample sandbox request

# Test SMS purchase (no real cost)
curl -X POST https://vanta.aces-portal.com/api/v1/sandbox/sms/orders \
  -H "X-API-Key: ik_test_YOUR_SANDBOX_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country": "United States", "service": "WhatsApp"}'

// Returns mock data instead of real number
{ "sandbox": true, "number": "+15557859130", "otp_code": null }

Ready to integrate?

Get your API keys from your developer dashboard and start building.

person_add Create an account