PleasureStock API v1.0
Complete B2B Integration API Documentation
🚀 Quick Start Guide
https://pleasurestock.com/api/v1⚠️ This is not a web page - use this URL in your code for API requests
Available APIs
Sexual wellness catalog, sales data, inventory
B2B partner integration, order management
Real-time order status updates
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
- Login to PleasureStock at https://pleasurestock.com
 - Navigate to Settings → API Keys
 - Click "Generate New Key"
 - Save your key immediately (shown only once!)
 
Authentication Methods
Method 1: X-API-Key Header (Standard API)
X-API-Key: pk_live_a1b2c3d4e5f6g7h8i9j0
Method 2: Bearer Token (External API)
Authorization: Bearer pk_live_a1b2c3d4e5f6g7h8i9j0
📦 Standard API Endpoints
Retrieve product catalog with filtering and pagination.
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 | 
Response Example
{
  "success": true,
  "data": [
    {
      "internal_id": "pl_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
  }
}
                    Submit sales data for Smart Reordering AI predictions and inventory tracking.
Request Body
{
  "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_idaccepts two formats:- UUID: 
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx(36 characters) - ps_id: 
ps_XXXXXXXXXX(starts with "ps_") 
- UUID: 
 datemust be valid ISO date (YYYY-MM-DD format)quantitymust be non-negative integerstock_on_handis optional, non-negative integer- Array 
salescan contain up to 1000 records per request 
Success Response
{
  "success": true,
  "message": "Sales data submitted successfully",
  "processed": 2
}
                    Error Response
{
  "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
}
                    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?
- ✅ Sales data is stored in PleasureStock
 - 🤖 AI automatically calculates Smart Reordering recommendations (once daily)
 - 📊 View recommendations at: Cart → Smart Reordering tab
 - 🎯 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_handfor best results 
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:
quantity→ SUM (total sales for the day)stock_on_hand→ MAX (highest stock level = total across warehouses)
Multiple Warehouses Support
If you have multiple warehouses, send data from each warehouse separately. The system will aggregate automatically:
{
  "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
 
{
  "sales": [{
    "internal_id": "ps_abc123",
    "date": "2025-11-03",
    "quantity": 0,           // No sales possible
    "stock_on_hand": 0       // ⚠️ Out of stock!
  }]
}
                    Get AI-powered inventory recommendations based on sales history.
Query Parameters
| Parameter | Type | Required | Description | 
|---|---|---|---|
| date | string | No | Target date for predictions (default: today) | 
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
Base URL:
https://pleasurestock.com/api/v1/externalRate Limit: 5000 requests/hour per API key
Create new orders in PleasureStock system. Items are automatically grouped by supplier.
Request Body
{
  "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
{
  "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
  }
}
                    Submit comprehensive sales data for AI-powered reordering recommendations.
Request Body
{
  "products": [
    {
      "ps_id": "ps_1234567890",
      "quantity": 15,
      "current_stock": 85,
      "sales_history": [5, 8, 12, 6, 9, 11, 7]
    }
  ]
}
                    Validation Requirements
ps_idmust start with "ps_" prefixquantitymust be non-negative numbercurrent_stockmust be non-negative numbersales_historymust contain at least 7 days of data
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, accepted) | 
| limit | integer | No | Results per page (default: 20) | 
| offset | integer | No | Skip records (default: 0) | 
Get detailed information about a specific order.
Update order status in the workflow.
Request Body
{
  "status": "paid",
  "externalOrderId": "EXT-123456",
  "comment": "Payment confirmed"
}
                    Status Workflow
created (System) → part_paid (External API) → paid (External API) → on_the_way (External API) → accepted (External API)
                    | 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 | 
accepted | 
                            External API | Goods received by buyer | Email to supplier | 
Receive webhook notifications for order events.
Webhook Events
order.confirmed- Order confirmed in systemorder.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:
X-Webhook-Signature: sha256=4f8b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b X-Webhook-Timestamp: 1736850600
Webhook Payload Examples
order.created Event
{
  "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
{
  "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
• 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
{
  "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
curl -X GET "https://pleasurestock.com/api/v1/products?limit=10" \ -H "X-API-Key: pk_live_your_api_key_here"
Python
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
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);
  });