PleasureStock API v1.0

Complete B2B Integration API Documentation

🤖 AI-Optimized Version Single page format for LLMs and automation

🚀 Quick Start Guide

Base URL for API calls: https://pleasurestock.com/api/v1
⚠️ This is not a web page - use this URL in your code for API requests

Available APIs

Rate Limits

Endpoint Type Requests/Hour Requests/Minute Burst Limit
Standard API 1,000 100 10/sec
External API 5,000 200 20/sec
Smart Reordering 100 10 2/sec

🔐 Authentication

Getting Your API Key

  1. Login to PleasureStock at https://pleasurestock.com
  2. Navigate to Settings → API Keys
  3. Click "Generate New Key"
  4. Save your key immediately (shown only once!)

Authentication Methods

Method 1: X-API-Key Header (Standard API)

HTTP Header
X-API-Key: pk_live_a1b2c3d4e5f6g7h8i9j0

Method 2: Bearer Token (External API)

HTTP Header
Authorization: Bearer pk_live_a1b2c3d4e5f6g7h8i9j0
Security Notice: Never expose your API key in client-side code or public repositories.

📦 Standard API Endpoints

GET /api/v1/products Stable

Retrieve product catalog with filtering and pagination.

✨ Updated 2025-11-10: Now supports Category, TCC (Total Current Cost), and TSP (Total Sale Price) fields!

Query Parameters

Parameter Type Required Description
page integer No Page number (default: 1)
limit integer No Items per page (max: 1000, default: 100)
supplier_id integer No Filter by supplier ID
search string No Search by name, SKU, or description
withImages boolean No Include product images (default: false)
includeCategory boolean No NEW: Include category information (default: false)
includeTcc boolean No NEW: Include TCC (Total Current Cost) calculations (default: false)
includeTsp boolean No NEW: Include TSP (Total Sale Price) calculations (default: false)

Response Example (Basic)

200 OK
{
  "success": true,
  "data": [
    {
      "internal_id": "ps_1234567890",
      "name": "Premium Silicone Vibrator",
      "sku": "VIB-001",
      "price": "49.99",
      "currency": "EUR",
      "supplier_id": 12,
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-03-20T14:45:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 100,
    "total": 1250,
    "pages": 13
  }
}

Response Example (With Category, TCC, TSP)

GET /api/v1/products?includeCategory=true&includeTcc=true&includeTsp=true
{
  "success": true,
  "data": [
    {
      "internal_id": "ps_1234567890",
      "name": "Premium Silicone Vibrator",
      "sku": "VIB-001",
      "price": "49.99",
      "currency": "EUR",
      "supplier_id": 12,

      // Category fields (includeCategory=true)
      "category_id": "c4f3e2d1-a2b3-4c5d-6e7f-8g9h0i1j2k3l",
      "category_name": "Вибраторы",
      "category_name_en": "Vibrators",

      // TCC fields (includeTcc=true)
      "tcc_enabled": true,
      "tcc_coefficient": 1.7,
      "tcc_total_cost": 84.98,
      "tcc_currency": "EUR",

      // TSP fields (includeTsp=true)
      "tsp_enabled": true,
      "tsp_value": 127.47,
      "tsp_formula": "TCC * 1.5",
      "tsp_currency": "EUR",

      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-03-20T14:45:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 100,
    "total": 1250,
    "pages": 13
  }
}

Field Explanations

Field Description
category_id UUID of the product category
category_name Category name in Russian
category_name_en Category name in English
tcc_enabled Whether TCC is enabled for your company
tcc_coefficient Multiplier for calculating total cost (e.g., 1.7 = +70% for shipping, taxes, customs)
tcc_total_cost Total Current Cost = price × coefficient (your actual procurement cost)
tsp_enabled Whether TSP is enabled for your company
tsp_value Total Sale Price - recommended retail price calculated from TCC using your formula
tsp_formula Your pricing formula (e.g., "TCC * 1.5", "TCC + 50")
📘 What are TCC and TSP?

TCC (Total Current Cost) - Your actual procurement cost including supplier price, shipping, taxes, and customs.
Configure in: Settings → TCC Settings

TSP (Total Sale Price) - Your recommended retail price calculated using a formula based on TCC.
Configure in: Settings → TSP Settings

Note: TCC and TSP are company-specific. Each API key sees their own company's calculations.

Usage Examples

Get products with categories only
curl -X GET 'https://pleasurestock.com/api/v1/products?page=1&limit=100&includeCategory=true' \
  -H 'X-API-Key: your-api-key-here'
Get products with pricing calculations
curl -X GET 'https://pleasurestock.com/api/v1/products?page=1&limit=100&includeTcc=true&includeTsp=true' \
  -H 'X-API-Key: your-api-key-here'
Get everything (category + TCC + TSP)
curl -X GET 'https://pleasurestock.com/api/v1/products?page=1&limit=100&includeCategory=true&includeTcc=true&includeTsp=true' \
  -H 'X-API-Key: your-api-key-here'
✨ New in 2025-11-11: Batch query support and single product endpoint!

🚀 Batch Query - Get Specific Products by IDs

Instead of fetching all products, you can request specific products using the ids parameter. This dramatically reduces API response size and improves performance.

Get specific products by IDs (batch query)
curl -X GET 'https://pleasurestock.com/api/v1/products?ids=ps_vj31ucxsab,ps_w2as53xl1z,ps_j2y58ajsit&includeCategory=true&includeTcc=true&includeTsp=true' \
  -H 'X-API-Key: your-api-key-here'
💡 Batch Query Benefits:
Performance: Request only products you need (26 products instead of 2490)
Bandwidth: Reduce API response size by 99%
Flexibility: Mix UUID and ps_* IDs in the same request
Format: Comma-separated list of IDs: ?ids=id1,id2,id3

Parameters

Parameter Type Description
ids string Optional. Comma-separated list of product IDs. Supports both UUID format (db57e260-b151-4bf1-ac63-175baef9f96d) and internal ID format (ps_vj31ucxsab). When provided, only returns specified products.
GET /api/v1/products/:id Stable

Get a single product by its ID (UUID or ps_* internal ID).

✨ New in 2025-11-11: Retrieve individual products without fetching the entire catalog!

URL Parameters

Parameter Type Description
id string Required. Product ID in UUID format (db57e260-b151-4bf1-ac63-175baef9f96d) or internal ID format (ps_vj31ucxsab).

Query Parameters

Parameter Type Default Description
withImages boolean true Include product images
includeCategory boolean false Include category information
includeTcc boolean false Include Total Current Cost calculations
includeTsp boolean false Include Total Sale Price calculations

Usage Examples

Get single product by ps_* ID
curl -X GET 'https://pleasurestock.com/api/v1/products/ps_vj31ucxsab?includeCategory=true&includeTcc=true&includeTsp=true' \
  -H 'X-API-Key: your-api-key-here'
Get single product by UUID
curl -X GET 'https://pleasurestock.com/api/v1/products/db57e260-b151-4bf1-ac63-175baef9f96d?includeCategory=true&includeTcc=true&includeTsp=true' \
  -H 'X-API-Key: your-api-key-here'

Response Example

Single Product Response
{
  "success": true,
  "data": {
    "id": "db57e260-b151-4bf1-ac63-175baef9f96d",
    "internal_id": "ps_vj31ucxsab",
    "name": "",
    "sku": "SL2505044-XCM",
    "price": "8.00",
    "currency": "USD",
    "supplier_id": "f0229142-b869-42c6-8751-9cb3d629e192",
    "created_at": "2025-11-04T08:34:35.815Z",
    "updated_at": "2025-11-04T08:45:47.291Z",

    // Category fields (includeCategory=true)
    "category_id": "3b4f0280-6396-44e0-a9b3-53931d4b5b92",
    "category_name": "Rabbit",
    "category_name_en": "Rabbit",

    // TCC fields (includeTcc=true)
    "tcc_enabled": true,
    "tcc_coefficient": 2,
    "tcc_total_cost": 16,
    "tcc_currency": "TRY",

    // TSP fields (includeTsp=true)
    "tsp_enabled": true,
    "tsp_value": 144,
    "tsp_formula": "TCC * 2.5 + 104",
    "tsp_currency": "TRY"
  }
}
💡 Use Case: Perfect for updating individual product information without fetching the entire catalog.
POST /api/v1/sales Stable

Submit sales data for Smart Reordering AI predictions and inventory tracking.

✨ Updated 2025-11-03: Now supports both UUID and ps_id formats for product identification!

Request Body

JSON
{
  "sales": [
    {
      "internal_id": "ps_uypjz2vraa",
      "date": "2025-11-03",
      "quantity": 15,
      "stock_on_hand": 120
    },
    {
      "internal_id": "b421eb2c-e1ee-4537-9c19-056d63a337c4",
      "date": "2025-11-03",
      "quantity": 8,
      "stock_on_hand": 45
    }
  ]
}

Request Parameters

Field Type Required Format Example
internal_id string ✅ Yes UUID or ps_id "ps_uypjz2vraa" or
"b421eb2c-e1ee-4537-9c19-056d63a337c4"
date string ✅ Yes YYYY-MM-DD "2025-11-03"
quantity integer ✅ Yes ≥ 0 15
stock_on_hand integer ❌ No ≥ 0 120

Validation Rules

  • internal_id accepts two formats:
    • UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (36 characters)
    • ps_id: ps_XXXXXXXXXX (starts with "ps_")
  • date must be valid ISO date (YYYY-MM-DD format)
  • quantity must be non-negative integer
  • stock_on_hand is optional, non-negative integer
  • Array sales can contain up to 1000 records per request

Success Response

200 OK
{
  "success": true,
  "message": "Sales data submitted successfully",
  "processed": 2
}

Error Response

400 Bad Request
{
  "error": "Validation errors",
  "errors": [
    {
      "index": 0,
      "error": "Invalid internal_id format",
      "expected": "UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) or ps_id (ps_XXXXXXXXXX)",
      "received": "invalid_id_123"
    }
  ],
  "processed": 0
}
💡 How to find product internal_id:
1. Login to PleasureStock
2. Go to Products section
3. Find your product by SKU
4. Column "PleasureStock ID" shows the internal_id

What Happens After Submission?

  1. ✅ Sales data is stored in PleasureStock
  2. 🤖 AI automatically calculates Smart Reordering recommendations (once daily)
  3. 📊 View recommendations at: Cart → Smart Reordering tab
  4. 🎯 See recommended quantities, current stock, and forecast accuracy

Best Practices

  • 📅 Frequency: Send data daily (minimum) or every 2-4 hours (optimal)
  • 📊 Historical Data: Submit past 30-90 days for better AI predictions
  • 📦 Batch Size: Up to 1000 records per request
  • 🎯 Accuracy: Always include stock_on_hand for best results
🌍 Idempotency (World-Class Best Practice):
You can safely send the same data multiple times - the system automatically deduplicates by date.

Example: If you send data for 2025-11-03 twice, the system will aggregate:
  • quantitySUM (total sales for the day)
  • stock_on_handMAX (highest stock level = total across warehouses)
This design follows Amazon MWS and Shopify API patterns.

Multiple Warehouses Support

If you have multiple warehouses, send data from each warehouse separately. The system will aggregate automatically:

Multiple Warehouses Example
{
  "sales": [
    {
      "internal_id": "ps_abc123",
      "date": "2025-11-03",
      "quantity": 10,          // Warehouse A sales
      "stock_on_hand": 500     // Warehouse A stock
    },
    {
      "internal_id": "ps_abc123",  // Same product, different warehouse
      "date": "2025-11-03",
      "quantity": 5,           // Warehouse B sales
      "stock_on_hand": 300     // Warehouse B stock
    }
  ]
}

Result: System aggregates to quantity: 15 (total sales) and stock_on_hand: 500 (max = total stock across all warehouses).

Out-of-Stock Days

When a product is out of stock, send stock_on_hand: 0. The AI will:

  • ✅ Exclude these days from average sales calculations
  • ✅ Mark them as OOS (Out-of-Stock) periods
  • ✅ Provide more accurate forecasts by ignoring zero-sales due to stockouts
Out-of-Stock Example
{
  "sales": [{
    "internal_id": "ps_abc123",
    "date": "2025-11-03",
    "quantity": 0,           // No sales possible
    "stock_on_hand": 0       // ⚠️ Out of stock!
  }]
}
GET /api/v1/smart-reordering Stable

Get AI-powered inventory recommendations based on sales history.

Query Parameters

Parameter Type Required Description
date string No Target date for predictions (default: today)
Note: Requires sales data submission for accurate predictions.
GET /api/v1/currency/convert-to-try Stable

Convert prices to Turkish Lira with real-time exchange rates.

Query Parameters

Parameter Type Required Description
amount number Yes Amount to convert
currency string Yes Source currency (EUR, USD, GBP)

🔗 External B2B Integration API

Authentication: External API uses Bearer token authentication.
Base URL: https://pleasurestock.com/api/v1/external
Rate Limit: 5000 requests/hour per API key
POST /api/v1/external/orders Stable

Create new orders in PleasureStock system. Items are automatically grouped by supplier.

Request Body

JSON
{
  "items": [
    {
      "ps_id": "ps_1234567890",
      "quantity": 10,
      "customPrice": 25.50  // optional, uses product price if not provided
    },
    {
      "ps_id": "ps_0987654321",
      "quantity": 5
    }
  ],
  "externalOrderId": "ERP-2025-001",  // your internal reference
  "comment": "Urgent order for customer ABC"
}

Response Example

200 OK
{
  "success": true,
  "data": {
    "orders": [
      {
        "orderNumber": "ORD-2025-000123",
        "deliveryId": "PS-2025-0114",
        "supplierId": 12,
        "status": "created",
        "totalAmount": 255.00,
        "currency": "USD",
        "items": 1,
        "createdAt": "2025-01-14T10:00:00Z"
      },
      {
        "orderNumber": "ORD-2025-000124",
        "deliveryId": "PS-2025-0115",
        "supplierId": 15,
        "status": "created",
        "totalAmount": 125.00,
        "currency": "USD",
        "items": 1,
        "createdAt": "2025-01-14T10:00:00Z"
      }
    ],
    "totalOrders": 2,
    "totalAmount": 380.00
  }
}
Important: Items are automatically grouped by supplier. One API call may create multiple orders.
POST /api/v1/external/smart-reorder Stable

Submit comprehensive sales data for AI-powered reordering recommendations.

Request Body

JSON
{
  "products": [
    {
      "ps_id": "ps_1234567890",
      "quantity": 15,
      "current_stock": 85,
      "sales_history": [5, 8, 12, 6, 9, 11, 7]
    }
  ]
}

Validation Requirements

  • ps_id must start with "ps_" prefix
  • quantity must be non-negative number
  • current_stock must be non-negative number
  • sales_history must contain at least 7 days of data
GET /api/v1/external/orders Stable

Retrieve all orders created by your API key with filtering options.

Query Parameters

Parameter Type Required Description
status string No Filter by status (created, part_paid, paid, on_the_way, delivered, accepted, cancelled)
limit integer No Results per page (default: 20)
offset integer No Skip records (default: 0)

Response Example

200 OK
{
  "success": true,
  "data": {
    "orders": [
      {
        "orderId": "a9e312b9-d5bb-4961-8db6-7ea1007e672b",
        "orderNumber": "ORD-20251103-78XZ70",
        "deliveryId": "PS-2025-1103/2",
        "externalOrderId": null,
        "status": "created",
        "statusDisplay": {
          "label": "Created",
          "color": "blue",
          "cssClass": "bg-blue-100 text-blue-800"
        },
        "supplierName": "Yiqing",
        "totalAmount": "5669.57",
        "currency": "USD",
        "itemsCount": 15,
        "hasCustomItems": false,
        "customItemsCount": 0,
        "catalogItemsCount": 15,
        "createdAt": "03/11/25",
        "statusChangedAt": "03/11/25"
      },
      {
        "orderId": "1c29979b-1a2a-4667-a84c-dfcf819dd044",
        "orderNumber": "ORD-20251103-LMGYAQ",
        "deliveryId": "PS-2025-1103/1",
        "status": "cancelled",
        "statusDisplay": {
          "label": "Cancelled",
          "color": "red",
          "cssClass": "bg-red-100 text-red-800"
        },
        "supplierName": "Yiqing",
        "totalAmount": "5669.57",
        "currency": "USD",
        "itemsCount": 15,
        "createdAt": "03/11/25",
        "statusChangedAt": "03/11/25"
      }
    ],
    "pagination": {
      "total": 8,
      "limit": 20,
      "offset": 0
    }
  }
}
💡 Tip: Use the statusDisplay object to show color-coded status badges in your UI. The cssClass uses Tailwind CSS classes.
GET /api/v1/external/orders/{orderNumber} Stable

Get detailed information about a specific order including all items and custom line items.

Response Example

200 OK
{
  "success": true,
  "data": {
    "orderId": "a9e312b9-d5bb-4961-8db6-7ea1007e672b",
    "orderNumber": "ORD-20251103-78XZ70",
    "deliveryId": "PS-2025-1103/2",
    "externalOrderId": null,
    "status": "created",
    "statusDisplay": {
      "label": "Created",
      "color": "blue",
      "cssClass": "bg-blue-100 text-blue-800"
    },
    "supplier": {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "name": "Yiqing"
    },
    "hasCustomItems": false,
    "items": [
      {
        "isCustom": false,
        "productId": "b421eb2c-e1ee-4537-9c19-056d63a337c4",
        "psId": "ps_uypjz2vraa",
        "product": {
          "name": "Premium Silicone Vibrator",
          "sku": "VIB-001",
          "imageUrl": "https://pleasurestock.com/uploads/products/vib001.jpg"
        },
        "quantity": 5,
        "unitPrice": "29.99",
        "totalPrice": "149.95",
        "currency": "USD"
      }
    ],
    "totalAmount": "5669.57",
    "currency": "USD",
    "estimatedDeliveryDate": "2025-11-20",
    "actualDeliveryDate": null,
    "createdAt": "03/11/25",
    "confirmedAt": "03/11/25",
    "paidAt": null,
    "shippedAt": null,
    "acceptedAt": null
  }
}
PUT /api/v1/external/orders/{orderNumber}/status Stable

Update order status in the workflow.

Request Body

JSON
{
  "status": "paid",
  "externalOrderId": "EXT-123456",
  "comment": "Payment confirmed"
}

Status Workflow

Order Status Lifecycle:
createdpart_paidpaidon_the_waydeliveredaccepted
Cancellation: Can be set from any non-final status → cancelled
Final statuses: accepted, cancelled
Status Set By Description Notifications
created System Order created, awaiting payment None
part_paid External API Partial payment received Email to supplier
paid External API Full payment confirmed Email to supplier
on_the_way External API Shipment dispatched Email to buyer
delivered External API Goods delivered to buyer (awaiting acceptance) Email to buyer and supplier
accepted External API Goods received and accepted by buyer (FINAL) Email to supplier
cancelled System/User Order cancelled (FINAL - cannot be changed) Email to buyer and supplier

📋 Best Practices for Working with Order Statuses

Filtering Active Orders (Exclude Cancelled):
To get only active orders and avoid cancelled duplicates, use status filters:
Get only active orders
GET /api/v1/external/orders?status=created
GET /api/v1/external/orders?status=paid
GET /api/v1/external/orders?status=on_the_way
Handling Duplicate Orders:
If you see multiple orders with identical content and amounts, check the status field:
• Orders with status: "cancelled" are NOT active
• Each order has unique orderId, orderNumber, and deliveryId
• Use deliveryId to identify the latest active order (e.g., PS-2025-1103/2 is newer than PS-2025-1103/1)

Using statusDisplay Field

The API returns a statusDisplay object with formatted status information:

statusDisplay object
{
  "status": "cancelled",
  "statusDisplay": {
    "label": "Cancelled",
    "color": "red",
    "cssClass": "bg-red-100 text-red-800"
  }
}

This field is useful for displaying order status in your UI with appropriate styling.

POST /api/v1/external/webhook Stable

Receive webhook notifications for order events.

Webhook Events

  • order.confirmed - Order confirmed in system
  • order.status_changed - Order status updated

🔔 Webhooks

Configuration

Configure webhook endpoints in Settings → API Keys → Webhook Configuration

Webhook Events

Event Trigger Payload
order.created New order created via API Full order details with items
order.status_changed Order status updated Order with old/new status
order.cancelled Order cancelled Order details with cancellation reason

Webhook Security

All webhook requests include HMAC-SHA256 signature for verification:

Headers
X-Webhook-Signature: sha256=4f8b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b
X-Webhook-Timestamp: 1736850600

Webhook Payload Examples

order.created Event

POST to your endpoint
{
  "event": "order.created",
  "timestamp": "2025-01-14T10:00:00Z",
  "data": {
    "orderId": "550e8400-e29b-41d4-a716-446655440000",
    "orderNumber": "ORD-2025-000123",
    "deliveryId": "PS-2025-0114",
    "status": "created",
    "supplierId": "550e8400-e29b-41d4-a716-446655440001",
    "totalAmount": 255.00,
    "currency": "USD",
    "items": [
      {
        "ps_id": "ps_1234567890",
        "quantity": 10,
        "unitPrice": 25.50,
        "totalPrice": 255.00
      }
    ],
    "externalOrderId": "ERP-2025-001",
    "createdAt": "2025-01-14T10:00:00Z"
  }
}

order.status_changed Event

POST to your endpoint
{
  "event": "order.status_changed",
  "timestamp": "2025-01-14T11:00:00Z",
  "data": {
    "orderId": "550e8400-e29b-41d4-a716-446655440000",
    "orderNumber": "ORD-2025-000123",
    "oldStatus": "created",
    "newStatus": "paid",
    "changedBy": "external_api",
    "comment": "Payment confirmed via bank transfer",
    "changedAt": "2025-01-14T11:00:00Z"
  }
}

Webhook Retry Mechanism

Automatic Retries: Failed webhook deliveries are retried with exponential backoff:
• 1st retry: After 2 seconds
• 2nd retry: After 4 seconds
• 3rd retry: After 8 seconds
• Timeout: 10 seconds per request
• Failed webhooks are queued for manual retry

⚠️ Error Handling

Error Response Format

Error Response
{
  "success": false,
  "error": "Invalid request",
  "message": "The request payload is invalid",
  "details": ["Missing required field: internal_id"]
}

HTTP Status Codes

Code Description Common Causes
200 Success Request processed successfully
400 Bad Request Invalid parameters, validation errors
401 Unauthorized Missing or invalid API key
403 Forbidden Insufficient permissions
404 Not Found Resource doesn't exist
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server-side error

💻 Code Examples

cURL

Get Products
curl -X GET "https://pleasurestock.com/api/v1/products?limit=10" \
  -H "X-API-Key: pk_live_your_api_key_here"

Python

Create Order via External API
import requests
import hashlib
import hmac
import time

class PleasureStockAPI:
    def __init__(self, api_key, webhook_secret=None):
        self.api_key = api_key
        self.webhook_secret = webhook_secret
        self.base_url = "https://pleasurestock.com/api/v1"
    
    def create_order(self, items, external_order_id=None, comment=None):
        """Create a new order in PleasureStock"""
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "items": items,
            "externalOrderId": external_order_id,
            "comment": comment
        }
        
        response = requests.post(
            f"{self.base_url}/external/orders",
            json=payload,
            headers=headers
        )
        
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"API Error: {response.text}")
    
    def update_order_status(self, order_number, status, comment=None):
        """Update order status"""
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {"status": status}
        if comment:
            payload["comment"] = comment
        
        response = requests.put(
            f"{self.base_url}/external/orders/{order_number}/status",
            json=payload,
            headers=headers
        )
        
        return response.json()
    
    def verify_webhook(self, signature, timestamp, body):
        """Verify webhook signature"""
        if not self.webhook_secret:
            return False
        
        message = f"{timestamp}.{body}"
        expected = hmac.new(
            self.webhook_secret.encode(),
            message.encode(),
            hashlib.sha256
        ).hexdigest()
        
        return f"sha256={expected}" == signature

# Example usage
api = PleasureStockAPI("pk_live_your_api_key_here")

# Create order
order = api.create_order(
    items=[
        {"ps_id": "ps_1234567890", "quantity": 10, "customPrice": 25.50},
        {"ps_id": "ps_0987654321", "quantity": 5}
    ],
    external_order_id="ERP-2025-001",
    comment="Urgent order"
)

print(f"Created {order['data']['totalOrders']} orders")
for o in order['data']['orders']:
    print(f"  - {o['orderNumber']}: ${o['totalAmount']}")

# Update status to paid
api.update_order_status(
    order['data']['orders'][0]['orderNumber'],
    "paid",
    "Payment confirmed"
)

Node.js

External API - Get Orders
const axios = require('axios');

class PleasureStockAPI {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseURL = 'https://pleasurestock.com/api/v1';
  }

  async getOrders(status = null) {
    try {
      const params = status ? { status } : {};
      
      const response = await axios.get(
        `${this.baseURL}/external/orders`,
        {
          headers: {
            'Authorization': `Bearer ${this.apiKey}`
          },
          params
        }
      );
      
      return response.data;
    } catch (error) {
      console.error('API Error:', error.response?.data || error.message);
      throw error;
    }
  }

  async updateOrderStatus(orderNumber, status, comment = '') {
    try {
      const response = await axios.put(
        `${this.baseURL}/external/orders/${orderNumber}/status`,
        { status, comment },
        {
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json'
          }
        }
      );
      
      return response.data;
    } catch (error) {
      console.error('API Error:', error.response?.data || error.message);
      throw error;
    }
  }
}

// Usage
const api = new PleasureStockAPI('pk_live_your_api_key_here');

// Get pending orders
api.getOrders('pending')
  .then(orders => {
    console.log(`Found ${orders.data.orders.length} pending orders`);
  });

// Update order status
api.updateOrderStatus('ORD-2024-001234', 'paid', 'Payment confirmed')
  .then(result => {
    console.log('Order updated:', result);
  });

🎮 API Playground

Enter your API key to test endpoints directly from this page.

Test API Connection