API documentation
Last updated May 22, 2026
Getting started with the YoungPG API
The YoungPG reseller API lets you browse our catalog and buy accounts programmatically. All endpoints are JSON, prefixed with /api/v1/, and gated by an API key.
1. Mint a key
Open your API dashboard and click + New key. Give it a label so you can tell it apart from other keys later, then pick the scopes you need. The plaintext key is shown once — copy it immediately.
2. Make your first call
curl https://youngpgmedia.com.ng/api/v1/user/balance \
-H "X-API-Key: ypg_..."
You should get back:
{
"success": true,
"data": { "balance_ngn": "0.00" }
}
3. Browse the catalog
curl "https://youngpgmedia.com.ng/api/v1/listings?per_page=5" \
-H "X-API-Key: ypg_..."
Each listing includes a price_ngn (already in naira at our current rate) and an available_stock count.
4. Make a purchase
POST /api/v1/purchase debits your wallet in naira and returns the credentials immediately:
curl -X POST https://youngpgmedia.com.ng/api/v1/purchase \
-H "X-API-Key: ypg_..." \
-H "Content-Type: application/json" \
-d '{"slug":"facebook-aged","quantity":2}'
That's the whole loop. Read the endpoint reference for the full surface, or the errors page for status codes and rate limits.
Authentication
Every call to /api/v1/* must include your API key in the X-API-Key header. Keys are minted from your dashboard and look like ypg_<48 hex chars>.
Showing the plaintext only once
When you create a key, the full plaintext is shown once. We store only the SHA-256 hash plus a 12-character prefix so you can identify the key in your dashboard later. If you lose the plaintext, revoke the key and mint a new one — there is no "view again".
Scopes
Each key carries a set of scopes that limit what it can do:
listings:read— browse categories and listingsorders:read— list your past ordersorders:write— callPOST /api/v1/purchaseprofile:read— read your YPG profileprofile:write— update your YPG profilewallet:read— read your NGN balance
A 403 with Scope required: <scope> means the key you used doesn't have the scope the endpoint needs.
Expiration
Keys can carry an optional expires_at. After that timestamp, calls return 401. You can mint a fresh key at any time.
Revoking a key
Use the Revoke button on a key row in your dashboard. Revocation is immediate.
Endpoint reference
All requests must include X-API-Key: ypg_.... All responses share the shape { "success": bool, "message": string?, "data": ..., "meta"?: ... }. Money values are NGN.
User
GET /api/v1/user/profile— your YPG profile.PUT /api/v1/user/profile— body{ first_name?, last_name?, phone?, country? }.GET /api/v1/user/balance—{ balance_ngn }.
Catalog
GET /api/v1/categories— every active category.GET /api/v1/categories/{id}/subcategories— drill-down.GET /api/v1/listings— query params:category_id,subcategory_id,search,sort(one ofsort_key,total_price,available_stock,title),direction(asc/desc),per_page(≤ 100),page.GET /api/v1/listings/{slug}— single listing detail.
Orders
POST /api/v1/purchase— body{ slug, quantity, promo_code? }. Returns{ order_id, accounts: ["email:password", ...], amount_ngn, new_balance_ngn }. Rate-limited at 10/min separately from the global 60/min.GET /api/v1/orders— paginated list of your orders.GET /api/v1/orders/{id}— single order including delivered credentials.
Promo
POST /api/v1/promo/validate— body{ code, slug, quantity }→ returns the NGN discount and final amount without placing the order.
Errors & rate limits
Errors share the same envelope as successes, with success: false:
{
"success": false,
"message": "Insufficient wallet balance",
"errors": null
}
Status codes
| Code | Meaning | |------|---------| | 200 | OK | | 201 | Resource created | | 400 | Business rule failed (e.g. insufficient balance, out of stock) | | 401 | Missing or invalid API key | | 403 | Scope missing, or account suspended | | 404 | Resource not found | | 422 | Body validation failed — errors contains per-field messages | | 429 | Rate limit exceeded — see Retry-After header | | 502 | Account delivery temporarily unavailable — retry shortly |
Rate limits
- Global per key: 60 requests per minute across all endpoints.
- Purchase endpoint: 10 requests per minute, on top of the global cap.
When you hit a limit you get a 429 with a Retry-After: <seconds> header. Back off for that many seconds before retrying — anything sooner just refreshes the cap.
Idempotency on purchase
POST /api/v1/purchase is not retry-safe. If a request times out or returns 502, do not simply retry — first call GET /api/v1/orders to see if the order actually landed. Double-retries can mean double-charges.