API Reference

REST API

The ForgeStore API lets you query your store data, verify purchases, and check player status programmatically. Perfect for custom game plugins and integrations.

🔑
Base URL: https://forgestore.net/api/v1
Format: All responses are JSON. All requests must include your API key.

Authentication

All API endpoints require authentication via your Store API Key. Find it in Store Settings → Details (the long alphanumeric string).

Pass the key in the X-Api-Key header with every request:

GET https://forgestore.net/api/v1/store
X-Api-Key: your_store_api_key_here
⚠️
Keep your API key secret. Don't commit it to public repositories. Each store has its own unique key. If compromised, regenerate it in Store Settings.

Endpoints

GET /api/v1/store Free
Returns basic information about the authenticated store.

Example Response

{
  "id": 42,
  "name": "Nexus Gaming",
  "subdomain": "nexus",
  "game": "minecraft",
  "currency": "EUR",
  "url": "https://forgestore.net/s/nexus"
}
GET /api/v1/packages
Returns all active packages for the store.

Example Response

{
  "packages": [
    {
      "id": 1,
      "name": "VIP Rank",
      "description": "Access to VIP perks and kit",
      "type": "single",
      "price_cents": 999,
      "webhook_product_id": "67afaa53ac949f9d80f31a08",
      "is_hidden": false,
      "image_url": "/uploads/images/abc123.jpg"
    }
  ],
  "count": 1
}
GET /api/v1/packages/{id}
Returns details for a specific package.
ParameterTypeDescription
idintegerPackage ID (URL parameter)
GET /api/v1/player/{username}/orders
Returns all paid orders for a specific player on this store. Use this to verify what a player has purchased.
ParameterTypeDescription
usernamestringThe in-game username (URL parameter)

Example Response

{
  "player": "Notch",
  "orders": [
    {
      "id": 101,
      "amount_cents": 999,
      "currency": "EUR",
      "status": "paid",
      "created_at": "2025-05-07 14:22:00",
      "package_name": "VIP Rank",
      "package_type": "single",
      "webhook_product_id": "67afaa53ac949f9d80f31a08"
    }
  ],
  "count": 1
}
GET /api/v1/player/{username}/has/{package_id}
Quick check: has a player purchased a specific package? Returns a boolean. Useful for permission systems.

Example Response

{
  "player": "Notch",
  "package_id": 1,
  "has_purchased": true,
  "purchase_count": 2
}
GET /api/v1/orders/{id}
Returns full details for a specific order. Useful for verifying payment after receiving a webhook.

Example Response

{
  "id": 101,
  "player_id": "Notch",
  "player_email": "[email protected]",
  "amount_cents": 999,
  "currency": "EUR",
  "status": "paid",
  "payment_method": "crypto",
  "external_id": "cm_uuid-here",
  "created_at": "2025-05-07 14:22:00",
  "package_name": "VIP Rank",
  "webhook_product_id": "67afaa53ac949f9d80f31a08"
}
GET /api/v1/bans/{username}
Check if a player is currently banned from the store. Useful to block banned players from purchasing via custom integrations.

Example Response

{
  "player": "griefer123",
  "is_banned": true,
  "ban": {
    "id": 5,
    "reason": "Chargeback abuse",
    "expires_at": null,
    "created_at": "2025-04-01 10:00:00"
  }
}

Webhooks

ForgeStore sends an HTTP POST to your server when specific events occur. Configure your webhook URL in Store Settings → Developers → Webhooks.

Supported Events

Webhook Payload — purchase

{
  "event": "purchase",
  "storeSlug": "nexus",
  "orderId": 101,
  "playerData": {
    "playerName": "Notch",
    "playerEmail": "[email protected]",
    "verified": true
  },
  "lineItems": [
    {
      "productId": "67afaa53ac949f9d80f31a08",
      "quantity": 1,
      "name": "VIP Rank",
      "priceCents": 999,
      "currency": "EUR"
    }
  ]
}

Verifying Webhook Signatures

Every webhook includes a signature in the X-ForgeStore-Signature header. Verify it to ensure the request is genuine:

// PHP example
$payload = file_get_contents('php://input');
$sig     = $_SERVER['HTTP_X_FORGESTORE_SIGNATURE'] ?? '';
$secret  = 'your_webhook_secret'; // From Store Settings → Developers

$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $sig)) {
    http_response_code(401);
    exit('Unauthorized');
}

$data = json_decode($payload, true);
// Process event...
if ($data['event'] === 'purchase') {
    $player  = $data['playerData']['playerName'];
    $product = $data['lineItems'][0]['productId'];
    // Grant items to player
}

Node.js Example (Express)

const express = require('express');
const crypto  = require('crypto');
const app     = express();

app.use(express.raw({ type: 'application/json' }));

app.post('/webhook', (req, res) => {
  const sig      = req.headers['x-forgestore-signature'];
  const secret   = process.env.WEBHOOK_SECRET;
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(req.body)
    .digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    return res.status(401).send('Unauthorized');
  }

  const event = JSON.parse(req.body);
  if (event.event === 'purchase') {
    const player  = event.playerData.playerName;
    const product = event.lineItems[0].productId;
    console.log(`Grant ${product} to ${player}`);
    // Your delivery logic here
  }

  res.json({ received: true });
});

app.listen(3000);

Error Codes

HTTP StatusCodeDescription
200OKRequest successful
400Bad RequestMissing or invalid parameters
401UnauthorizedMissing or invalid X-Api-Key
403ForbiddenYou don't have access to this resource
404Not FoundResource doesn't exist or doesn't belong to your store
429Too Many RequestsRate limit exceeded — 120 requests/minute
500Server ErrorSomething went wrong on our end — try again

Error Response Format

{
  "error": "Invalid API key"
}

Rate Limits

The API is rate limited to 120 requests per minute per API key. If you exceed this, you'll receive a 429 Too Many Requests response. The response includes a Retry-After header with the number of seconds to wait.


← Crypto Guide FAQ →

POST /api/v1/checkout

Create a checkout session for one or multiple packages. Returns a hosted checkout URL to redirect the player to.

RequestJSON
{
  "player_id": "Steve",
  "package_ids": [1, 2, 3],
  "email": "[email protected]"
}
ResponseJSON
{
  "checkout_url": "https://forgestore.net/checkout/basket?...",
  "player_id": "Steve",
  "packages": [
    { "id": 1, "name": "VIP", "price": 999 }
  ],
  "total_cents": 999,
  "currency": "EUR",
  "expires_at": "2026-06-09T14:00:00Z"
}

GET /api/v1/stats

Store statistics. Use ?days=30 to filter by period.

ResponseJSON
{
  "total_orders": 142,
  "total_revenue": 189900,
  "period_orders": 18,
  "period_revenue": 24500,
  "currency": "EUR",
  "period_days": 30
}

GET /api/v1/goals

List active community goals.

ResponseJSON
{
  "data": [
    {
      "id": 1,
      "title": "New Map",
      "target_cents": 50000,
      "current_cents": 23400,
      "currency": "EUR",
      "deadline": "2026-07-01",
      "is_active": 1
    }
  ]
}