Reseller API

Programmatic access to products, wallet balance, orders and instant delivery.

Base URL

https://tgcenter.mediacraftshop.com/api/public/v2

Every response is JSON and always contains an ok boolean. Errors add error: { code, message }.

Authentication

v2 uses a key + secret pair. The key identifies the credential, the secret proves ownership.

X-API-Key: rk_live_xxxxxxxx
X-API-Secret: rs_xxxxxxxxxxxxxxxx

# The key may also be sent as a bearer token:
Authorization: Bearer rk_live_xxxxxxxx
X-API-Secret: rs_xxxxxxxxxxxxxxxx

Signed requests (optional, recommended)

Credentials with require_signature enabled must send an HMAC-SHA256 signature over <timestamp>.<nonce>.<rawBody> using your API secret. Timestamps must be within 5 minutes and every nonce may only be used once (replay protection).

X-API-Key: rk_live_xxxxxxxx
X-Timestamp: 1780000000
X-Nonce: 6f1c1b6e-1b3f-4a4e-9f0e-2b7d9c1a5e77
X-Signature: hmac_sha256(secret, "1780000000.<nonce>.<rawBody>")
// Node.js
import { createHmac, randomUUID } from "crypto";

const body = JSON.stringify({ product_id: PRODUCT_ID, quantity: 1 });
const ts = Math.floor(Date.now() / 1000);
const nonce = randomUUID();
const signature = createHmac("sha256", API_SECRET)
  .update(`${ts}.${nonce}.${body}`)
  .digest("hex");

Idempotency

Send Idempotency-Key (or client_request_id in the body) on order creation. Repeating the same value returns the original order instead of charging twice.

Endpoints

1. Service index

GET https://tgcenter.mediacraftshop.com/api/public/v2
{
  "ok": true,
  "version": "v2",
  "endpoints": ["/me", "/balance", "/products", "/products/{id}", "/orders", "/orders/{id}"]
}

2. Account profile

GET https://tgcenter.mediacraftshop.com/api/public/v2/me
{
  "ok": true,
  "reseller": {
    "id": "RESELLER_UUID",
    "display_name": "Acme Digital",
    "email": "you@example.com",
    "status": "active",
    "discount_percent": 10
  },
  "credential": { "key_prefix": "rk_live_ab12", "rate_limit_per_minute": 120 },
  "wallet": { "balance": 125.5, "currency": "BDT" }
}

3. Wallet balance

GET https://tgcenter.mediacraftshop.com/api/public/v2/balance
{
  "ok": true,
  "balance": 125.5,
  "lifetime_credited": 900,
  "lifetime_debited": 774.5,
  "discount_percent": 10
}

4. List products

Prices already include your discount. Products with options expose a variants array — order the variant, not the parent product.

GET https://tgcenter.mediacraftshop.com/api/public/v2/products
GET https://tgcenter.mediacraftshop.com/api/public/v2/products?category_id=<uuid>&in_stock=true&limit=100
{
  "ok": true,
  "count": 1,
  "discount_percent": 10,
  "products": [
    {
      "id": "PRODUCT_UUID",
      "name": "Product name",
      "category_id": "CATEGORY_UUID",
      "auto_deliver": true,
      "stock": 25,
      "list_price": 10,
      "your_price": 9,
      "variants": [
        { "id": "VARIANT_UUID", "name": "12 months", "stock": 8, "list_price": 20, "your_price": 18 }
      ]
    }
  ]
}

5. Single product

GET https://tgcenter.mediacraftshop.com/api/public/v2/products/{id}

6. Place an order

POST https://tgcenter.mediacraftshop.com/api/public/v2/orders
X-API-Key: rk_live_xxxxxxxx
X-API-Secret: rs_xxxxxxxxxxxxxxxx
Idempotency-Key: your-unique-id
Content-Type: application/json

{
  "product_id": "PRODUCT_UUID",
  "variant_id": "VARIANT_UUID",
  "quantity": 1,
  "external_ref": "your-internal-order-id",
  "custom_data": {}
}
{
  "ok": true,
  "duplicate": false,
  "order": {
    "id": "ORDER_UUID",
    "status": "delivered",
    "quantity": 1,
    "unit_price": 18,
    "total": 18,
    "delivered": true,
    "delivery": { "text": "Activation data", "image_url": null, "video_url": null, "note": null }
  },
  "balance": 107.5
}

The wallet is debited and stock is reserved in a single atomic transaction — a failed delivery never loses your balance, and a successful debit never oversells stock.

7. Order history & status

GET https://tgcenter.mediacraftshop.com/api/public/v2/orders?limit=50&status=delivered
GET https://tgcenter.mediacraftshop.com/api/public/v2/orders/{id}
{
  "ok": true,
  "order": {
    "id": "ORDER_UUID",
    "product_name": "Product name",
    "variant_name": "12 months",
    "quantity": 1,
    "price": 18,
    "status": "delivered",
    "created_at": "2026-06-20T10:00:00.000Z",
    "delivered_at": "2026-06-20T10:00:03.000Z"
  }
}

cURL examples

curl -s "https://tgcenter.mediacraftshop.com/api/public/v2/me" \
  -H "X-API-Key: $API_KEY" \
  -H "X-API-Secret: $API_SECRET"
curl -s -X POST "https://tgcenter.mediacraftshop.com/api/public/v2/orders" \
  -H "X-API-Key: $API_KEY" \
  -H "X-API-Secret: $API_SECRET" \
  -H "Idempotency-Key: order-1001" \
  -H "Content-Type: application/json" \
  -d '{"product_id":"PRODUCT_UUID","quantity":1,"external_ref":"order-1001"}'

Webhooks

Register HTTPS endpoints in the Reseller Portal → Webhooks. We POST signed JSON for order.created, order.delivered, wallet.credited and wallet.debited. Reply with any 2xx status within 10 seconds. Non-2xx responses are retried up to 5 times with exponential backoff (1m, 2m, 4m, 8m, 16m).

POST /your/endpoint
X-TGC-Event: order.delivered
X-TGC-Event-Id: evt_9f21...
X-TGC-Timestamp: 1730000000
X-TGC-Signature: t=1730000000,v1=<hex>

{
  "id": "evt_9f21...",
  "event": "order.delivered",
  "api_version": "v2",
  "created": 1730000000,
  "reseller_id": "<uuid>",
  "data": { "order_id": "<uuid>", "total": 120, "delivery": { "text": "..." } }
}

Verify with HMAC_SHA256(secret, "<timestamp>.<raw body>") and compare against v1 using a timing-safe comparison. Reject timestamps older than 5 minutes and treat X-TGC-Event-Id as the idempotency key.

Error codes

  • missing_credentials / invalid_api_key — 401
  • invalid_signature / stale_request / replay_detected — 401
  • credential_revoked, reseller_suspended, reseller_pending — 403
  • insufficient_balance — 402
  • product_unavailable / variant_unavailable — 404
  • insufficient_stock — 409
  • rate_limited — 429

Store the key and secret in server-side environment variables only. Rotate them from the reseller portal at any time — old credentials stop working immediately.