# Zero API Documentation > AI-readable API documentation for the Zero e-commerce platform Base URL: https://00pays.com/api/v1 ## Authentication ### API Key Authentication Include API key in request headers: ``` X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxx ``` Or: ``` Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxx ``` ### OAuth 2.0 For third-party apps, use OAuth 2.0 authorization code flow: 1. Redirect to /api/v1/apps/oauth/authorize with client_id, redirect_uri, scope, state 2. User approves access 3. Exchange code for token at /api/v1/apps/oauth/token ## Response Format Success: ```json { "status": "ok", "message": "Success", "data": {} } ``` Error: ```json { "status": "error", "code": "ERROR_CODE", "message": "Error description" } ``` ## Rate Limiting API requests are rate-limited to ensure fair usage and system stability. ### Default Limits | Plan | Requests/Hour | |------|---------------| | Default Rate Limit | 100 | | Standard Plan | 1000 | | Premium Plan | 10000 | | OAuth App | 500 | ### Response Headers Rate limit information is included in response headers: ``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1704067200 Retry-After: 60 ``` ### Handling Rate Limits When rate limited, the API returns HTTP 429 with: ```json { "status": "error", "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded. Please wait before retrying.", "retryAfter": 60 } ``` Use the `Retry-After` header to determine when to retry. ## Webhooks Configure your webhook URL in store settings to receive real-time notifications. Every event is delivered as a POST with this envelope: ```json { "event": "event.name", "storeId": "store_id", "createdAt": "2024-01-15T10:30:00.000Z", "data": {} } ``` The `data` block also includes `ip`, `userAgent`, `sourceUrl`, and a unique `eventId` for deduplication. ### Verifying the signature Every delivery carries these headers: - `X-Zero-Event`: the event id - `X-Idempotency-Key`: stable per event across retries, use it to deduplicate - `X-Zero-Signature`: `sha256=`, an HMAC-SHA256 of the raw request body The signature is only sent once a webhook signing secret exists for the store. Generate one in the dashboard under Settings > Webhooks, then compare it against the RAW body bytes before parsing the JSON. Reject any request whose signature does not match. ```js const crypto = require('crypto'); // Express: capture the raw body, since re-serializing the parsed JSON // will not reproduce the exact bytes that were signed. app.post('/zero-webhook', express.raw({ type: 'application/json' }), (req, res) => { const expected = 'sha256=' + crypto .createHmac('sha256', process.env.ZERO_WEBHOOK_SECRET) .update(req.body) .digest('hex'); const received = req.headers['x-zero-signature'] || ''; const ok = expected.length === received.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received)); if (!ok) return res.status(401).end(); const event = JSON.parse(req.body.toString('utf8')); // ... handle the event, then always answer 2xx res.sendStatus(200); }); ``` Failed deliveries (non-2xx or timeout) are retried 3 times with a 1s, 5s, 15s backoff, so your endpoint must be idempotent on `X-Idempotency-Key`. ### Available Events #### Orders - **order.created**: Fired when a new order is placed (storefront checkout or dashboard order create) - **order.updated**: Fired when an order is modified (status, delivery, address, etc.) - **order.paid**: Fired when an order transitions to the paid state - **order.cancelled**: Fired when an order is cancelled from the dashboard #### Carts - **cart.created**: Fired when a customer adds the first item to a new cart - **cart.abandoned**: Fired hourly for carts with items idle for more than 1 hour. Re-fires if the customer re-engages then re-abandons. - **cart.coupon.applied**: Fired when a customer applies a coupon to their cart #### Customers - **customer.created**: Fired when a new customer registers in the storefront - **customer.loggedin**: Fired when a customer signs into the storefront #### Products - **product.created**: Fired when a new product is created from the dashboard - **product.updated**: Fired when a product is updated from the dashboard #### Reviews - **review.store.added**: Fired when a customer submits a store-level review - **review.product.added**: Fired when a customer submits a product review ## Available Scopes - *****: Complete access to all API endpoints - **products.read**: View products and product details - **products.write**: Create, update, and delete products - **products.***: Complete access to products - **orders.read**: View orders and order details - **orders.write**: Update order status and details - **orders.***: Complete access to orders - **customers.read**: View customer information - **customers.write**: Update customer information - **customers.***: Complete access to customers - **coupons.read**: View coupons and their details - **coupons.write**: Create, update, and delete coupons - **coupons.***: Complete access to coupons - **analytics.read**: View store analytics and reports - **settings.read**: View store settings - **settings.write**: Update store settings - **settings.***: Complete access to settings - **cart.read**: View shopping cart data - **cart.write**: Modify shopping cart - **reviews.read**: View product and store reviews - **reviews.write**: Manage reviews (approve, reject, respond) - **shipping.read**: View shipping information - **shipping.write**: Create shipping labels and manage shipping - **shipping.***: Complete access to shipping - **webhooks.subscribe**: Receive webhook notifications - **paylinks.read**: View payment links - **paylinks.write**: Create and manage payment links - **pages.read**: View store pages and their content - **pages.write**: Create, update, and delete store pages - **pages.***: Complete access to store pages - **design.read**: View store design, theme, and sections - **design.write**: Update store design, theme, and sections - **design.***: Complete access to store design ## API Endpoints ### Products Base path: /api/v1/dashboard/:storeId/products #### GET / **List products** Retrieve a paginated list of products with optional filtering Required scopes: products.read, products.* Parameters: - search: string - Search by product title - category: string - Filter by category ID - limit: number [default: 40] - Maximum results to return - skip: number [default: 0] - Number of results to skip (for pagination) - sort: number [1|-1] [default: -1] - Sort order (1: oldest first, -1: newest first) Example: ```javascript fetch(baseUrl + '/products?search=shirt&limit=20', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST / **Create product** Create a new product in the store Required scopes: products.write, products.* Parameters: - title: string (required) - Product title - price: number (required) - Product price - productType: string (required) [normal|digital|code|service] - Type of product - quantity: number [default: -1] - Stock quantity (-1 for unlimited) - currency: string [default: SAR] - Currency code - description: string - Product description (HTML supported) - categories: array - Array of category IDs - images: array - Array of image URLs or base64 encoded images - customFields: array - Custom fields for product - variants: array - Product variants (sizes, colors, etc.) Example: ```javascript fetch(baseUrl + '/products', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ title: 'New Product', price: 99.99, productType: 'normal', quantity: 100 }) }) ``` #### GET /:productId **Get product details** Retrieve detailed information about a specific product Required scopes: products.read, products.* Parameters: - productId: string (required) - Product ID Example: ```javascript fetch(baseUrl + '/products/507f1f77bcf86cd799439011', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### PATCH /:productId **Update product** Update an existing product. Only send fields you want to change. Required scopes: products.write, products.* Parameters: - productId: string (required) - Product ID - title: string - Product title - price: number - Product price - quantity: number - Stock quantity - description: string - Product description - categories: array - Category IDs - accessibility: string [public|private|archived] - Product visibility Example: ```javascript fetch(baseUrl + '/products/507f1f77bcf86cd799439011', { method: 'PATCH', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ price: 149.99, quantity: 50 }) }) ``` #### DELETE /:productId **Delete product** Delete a product from the store (archives it) Required scopes: products.write, products.* Parameters: - productId: string (required) - Product ID Example: ```javascript fetch(baseUrl + '/products/507f1f77bcf86cd799439011', { method: 'DELETE', headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST /:productId/duplicate **Duplicate product** Create a copy of an existing product Required scopes: products.write, products.* Parameters: - productId: string (required) - Product ID to duplicate Example: ```javascript fetch(baseUrl + '/products/507f1f77bcf86cd799439011/duplicate', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` ### Orders Base path: /api/v1/dashboard/:storeId/orders #### GET / **List orders** Retrieve a paginated list of orders with optional filtering Required scopes: orders.read, orders.* Parameters: - page: number [default: 1] - Page number - limit: number [default: 20] - Results per page - status: string [pending|confirmed|delivering|delivered|cancelled] - Filter by order status - paymentStatus: string [paid|pending|failed|refunded] - Filter by payment status - search: string - Search by order ID or customer info - startDate: string - Filter from date (ISO format) - endDate: string - Filter to date (ISO format) Example: ```javascript fetch(baseUrl + '/orders?status=pending&limit=50', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### GET /:orderId **Get order details** Retrieve detailed information about a specific order Required scopes: orders.read, orders.* Parameters: - orderId: string (required) - Order ID Example: ```javascript fetch(baseUrl + '/orders/507f1f77bcf86cd799439011', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### PATCH /:orderId **Update order** Update order status, payment status, or other details Required scopes: orders.write, orders.* Parameters: - orderId: string (required) - Order ID - status: string [pending|confirmed|delivering|delivered|cancelled] - Order status - paymentStatus: string [paid|pending|failed|refunded] - Payment status - trackingNumber: string - Shipping tracking number - notes: string - Internal notes Example: ```javascript fetch(baseUrl + '/orders/507f1f77bcf86cd799439011', { method: 'PATCH', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ status: 'delivering', trackingNumber: 'TRACK123456' }) }) ``` #### GET /unseen-count **Get unseen orders count** Get the count of orders that have not been viewed Required scopes: orders.read, orders.* Example: ```javascript fetch(baseUrl + '/orders/unseen-count', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST /export **Export orders to CSV** Export orders to a CSV file with optional filtering Required scopes: orders.read, orders.* Parameters: - startDate: string - Start date (ISO format) - endDate: string - End date (ISO format) - status: string - Filter by status Example: ```javascript fetch(baseUrl + '/orders/export', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ startDate: '2024-01-01', endDate: '2024-01-31' }) }) ``` ### Customers Base path: /api/v1/dashboard/:storeId/customers #### GET / **List customers** Retrieve a paginated list of customers Required scopes: customers.read, customers.* Parameters: - page: number [default: 1] - Page number - limit: number [default: 20] - Results per page - search: string - Search by name, email, or phone Example: ```javascript fetch(baseUrl + '/customers?search=ahmed&limit=20', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### GET /:customerId **Get customer details** Retrieve detailed information about a customer including recent orders Required scopes: customers.read, customers.* Parameters: - customerId: string (required) - Customer ID Example: ```javascript fetch(baseUrl + '/customers/507f1f77bcf86cd799439011', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST /export **Export customers to CSV** Export customer data to a CSV file Required scopes: customers.read, customers.* Example: ```javascript fetch(baseUrl + '/customers/export', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` ### Coupons Base path: /api/v1/dashboard/:storeId/coupons #### GET / **List coupons** Retrieve all coupons for the store Required scopes: coupons.read, coupons.* Parameters: - archived: boolean [default: false] - Include archived coupons Example: ```javascript fetch(baseUrl + '/coupons', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST / **Create coupon** Create a new discount coupon Required scopes: coupons.write, coupons.* Parameters: - couponId: string (required) - Coupon code (unique) - discountType: string (required) [percentage|fixed] - Type of discount - amount: number (required) - Discount amount (percentage or fixed value) - minPurchase: number [default: 0] - Minimum purchase amount - maxUses: number [default: 0] - Maximum uses (0 = unlimited) - expiryDate: string - Expiry date (ISO format) - applicableProducts: array - Product IDs the coupon applies to (empty = all) - applicableCategories: array - Category IDs the coupon applies to Example: ```javascript fetch(baseUrl + '/coupons', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ couponId: 'SAVE20', discountType: 'percentage', amount: 20, maxUses: 100 }) }) ``` #### GET /:couponId **Get coupon details** Retrieve detailed information about a specific coupon Required scopes: coupons.read, coupons.* Parameters: - couponId: string (required) - Coupon ID Example: ```javascript fetch(baseUrl + '/coupons/507f1f77bcf86cd799439011', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### PATCH /:couponId **Update coupon** Update an existing coupon Required scopes: coupons.write, coupons.* Parameters: - couponId: string (required) - Coupon ID - amount: number - Discount amount - minPurchase: number - Minimum purchase amount - maxUses: number - Maximum uses - expiryDate: string - Expiry date - isActive: boolean - Active status Example: ```javascript fetch(baseUrl + '/coupons/507f1f77bcf86cd799439011', { method: 'PATCH', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 25, maxUses: 200 }) }) ``` #### DELETE /:couponId **Delete coupon** Delete (archive) a coupon Required scopes: coupons.write, coupons.* Parameters: - couponId: string (required) - Coupon ID Example: ```javascript fetch(baseUrl + '/coupons/507f1f77bcf86cd799439011', { method: 'DELETE', headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` ### Categories Base path: /api/v1/dashboard/:storeId/categories #### GET / **List categories** Retrieve all categories for the store Required scopes: products.read, products.* Example: ```javascript fetch(baseUrl + '/categories', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST / **Create category** Create a new product category Required scopes: products.write, products.* Parameters: - name: string (required) - Category name - description: string - Category description - isActive: boolean [default: true] - Is category active - parentId: string - Parent category ID for nested categories - image: string - Category image URL or base64 Example: ```javascript fetch(baseUrl + '/categories', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Electronics', description: 'Electronic devices and accessories', isActive: true }) }) ``` #### PATCH /:categoryId **Update category** Update an existing category Required scopes: products.write, products.* Parameters: - categoryId: string (required) - Category ID - name: string - Category name - description: string - Category description - isActive: boolean - Is category active - parentId: string - Parent category ID Example: ```javascript fetch(baseUrl + '/categories/507f1f77bcf86cd799439011', { method: 'PATCH', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Electronics & Gadgets', isActive: true }) }) ``` #### DELETE /:categoryId **Delete category** Delete a category. Products in this category will be uncategorized. Required scopes: products.write, products.* Parameters: - categoryId: string (required) - Category ID Example: ```javascript fetch(baseUrl + '/categories/507f1f77bcf86cd799439011', { method: 'DELETE', headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST /sort **Sort categories** Update the display order of categories Required scopes: products.write, products.* Parameters: - categories: array (required) - Array of {id, order} objects Example: ```javascript fetch(baseUrl + '/categories/sort', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ categories: [ { id: 'cat1', order: 0 }, { id: 'cat2', order: 1 }, { id: 'cat3', order: 2 } ] }) }) ``` ### Paylinks Base path: /api/v1/dashboard/:storeId/paylinks #### GET / **List paylinks** Retrieve all non-archived paylinks for the store. Each item is enriched with `views`, `uniqueViews`, `conversions`, and `revenue` aggregated from store events and paid orders. Required scopes: paylinks.read, paylinks.* Example: ```javascript fetch(baseUrl + '/paylinks', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST / **Create paylink** Create a new paylink. All body fields are optional - omit `amount`/`title` to build a paylink driven entirely by `products`. The handler returns a freshly-minted 16-char `paylinkId` you can share as `https:///pay/`. Required scopes: paylinks.add, paylinks.* Parameters: - title: string - Display title shown to the customer at checkout. - description: string - Free-form description shown alongside the title. - amount: number - Charge amount in major units. Coerced via `Number()`. - currency: string - 3-letter ISO code (passed through as-is). - mode: enum [one-time|recurring] [default: recurring] - One-time paylinks lock after the first paid order (`consumedAt` is stamped). Recurring is the default and accepts unlimited paid orders. - products: object - Object keyed by productId mapping to `{ quantity, ... }`. Used by storefront-style paylinks where the customer pays for a cart instead of a flat amount. - prefilledCustomer: object - Optional `{ name, email, phone }` snapshotted onto the order so the merchant can issue a quick bill without asking again. Each field is trimmed and capped (name/email 200 chars, phone 50). Example: ```javascript fetch(baseUrl + '/paylinks', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ title: 'Consulting Service', amount: 500, currency: 'SAR', mode: 'recurring', description: 'One hour consulting session' }) }) ``` #### GET /:paylinkId **Get paylink** Retrieve a single paylink. The `paylinkId` argument matches the 16-char id, the doc's slug, or a 24-char ObjectId. Required scopes: paylinks.read, paylinks.* Parameters: - paylinkId: string (required) - paylinkId, slug, or _id. Example: ```javascript fetch(baseUrl + '/paylinks/a1b2c3d4e5f6g7h8', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### PATCH /:paylinkId **Update paylink** Partially update a paylink. Only the listed fields are accepted; everything else is silently ignored. `updatedAt` is stamped automatically. Required scopes: paylinks.edit, paylinks.* Parameters: - paylinkId: string (required) - paylinkId, slug, or _id. - title: string - Updated title. - description: string - Updated description. - amount: number - New amount (coerced via `Number()`). - currency: string - 3-letter ISO code. - isActive: boolean - Toggle the paylink on/off. - expiresAt: string - Expiry timestamp (ISO 8601). Pass `null` to clear. - maxUses: number - Cap on the number of paid orders allowed (0 = unlimited). - mode: enum [one-time|recurring] - Switch lifecycle. Setting `one-time` does not retroactively consume past orders. - prefilledCustomer: object - `{ name, email, phone }` (or `null` to clear). Same trim/cap rules as create. Example: ```javascript fetch(baseUrl + '/paylinks/a1b2c3d4e5f6g7h8', { method: 'PATCH', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 600, description: 'Updated description' }) }) ``` #### GET /:paylinkId/analytics **Get paylink analytics** Aggregated stats for one paylink: views (page_view events), unique viewers, conversions (paid orders, amount > 0), and revenue. Required scopes: paylinks.read, paylinks.* Parameters: - paylinkId: string (required) - paylinkId, slug, or _id. Example: ```javascript fetch(baseUrl + '/paylinks/a1b2c3d4e5f6g7h8/analytics', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### DELETE /:paylinkId **Delete paylink** Soft-deletes the paylink (sets `archived: true`). The id stays valid for analytics queries; the record is filtered out of `GET /paylinks` only. Required scopes: paylinks.delete, paylinks.* Parameters: - paylinkId: string (required) - paylinkId, slug, or _id. Example: ```javascript fetch(baseUrl + '/paylinks/a1b2c3d4e5f6g7h8', { method: 'DELETE', headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` ### Quick Paylinks Base path: /api/v1/paylinks #### POST /quick **Create a quick paylink** Create a one-time paylink hosted at 00pays.com using just a title and amount. The API key resolves the store, so callers do not need a storeId. The returned URL is share-anywhere - WhatsApp, SMS, email, etc. Required scopes: paylinks.add, paylinks.* Parameters: - title: string (required) - Title shown to the customer at checkout (max 200 chars). - amount: number (required) - Charge amount in major units (e.g. 99 for SAR 99). - currency: string - 3-letter ISO code. Defaults to the store's currency, falling back to SAR. - customer: object - Optional `{ name, email, phone }` to prefill the checkout form. - metadata: object - Flat key/value pairs (string|number|boolean) - opaque to the platform, returned later via the dashboard endpoint. Up to 32 keys, ~10KB total. Example: ```javascript curl -X POST 'https://00pays.com/api/v1/paylinks/quick' \ -H 'X-API-Key: ' \ -H 'Content-Type: application/json' \ -d '{ "title": "Order #1234", "amount": 99, "metadata": { "orderId": "abc-123", "channel": "whatsapp" } }' ``` #### GET /:paylinkId/status **Check quick paylink payment status** Lightweight status check for a one-time paylink. Use this from a webhook poller or a CRM to know if the customer paid yet. Returns `paid` or `unpaid`, plus the resulting order id and amount when paid. Required scopes: paylinks.read, paylinks.* Parameters: - paylinkId: string (required) - The id returned by `POST /paylinks/quick` (the same value as `data.paylinkId`). Example: ```javascript curl 'https://00pays.com/api/v1/paylinks/a1b2c3d4e5f6g7h8/status' \ -H 'X-API-Key: ' ``` ### Reviews Base path: /api/v1/dashboard/:storeId/reviews #### GET / **List reviews** Retrieve all reviews for the store Required scopes: reviews.read, reviews.* Parameters: - type: string [product|store] - Filter by review type - page: number [default: 1] - Page number - limit: number [default: 20] - Results per page - status: string [pending|approved|rejected] - Filter by status - archived: boolean [default: false] - Include archived reviews Example: ```javascript fetch(baseUrl + '/reviews?type=product&status=pending', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### PATCH /:reviewId **Update review** Update review status, visibility, or add a response Required scopes: reviews.write, reviews.* Parameters: - reviewId: string (required) - Review ID - status: string [pending|approved|rejected] - Review status - isPublic: boolean - Show on store - response: string - Store owner response Example: ```javascript fetch(baseUrl + '/reviews/507f1f77bcf86cd799439011', { method: 'PATCH', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ status: 'approved', isPublic: true, response: 'Thank you for your feedback!' }) }) ``` #### DELETE /:reviewId **Delete review** Permanently delete a review Required scopes: reviews.write, reviews.* Parameters: - reviewId: string (required) - Review ID Example: ```javascript fetch(baseUrl + '/reviews/507f1f77bcf86cd799439011', { method: 'DELETE', headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` ### Settings Base path: /api/v1/dashboard/:storeId/settings #### GET / **Get all settings** Retrieve all store settings Required scopes: settings.read, settings.* Example: ```javascript fetch(baseUrl + '/settings', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### PATCH /general **Update general settings** Update store general settings Required scopes: settings.write, settings.* Parameters: - name: string - Store name - description: string - Store description - currency: string - Default currency code - language: string - Default language - timezone: string - Timezone Example: ```javascript fetch(baseUrl + '/settings/general', { method: 'PATCH', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Updated Store Name', currency: 'USD' }) }) ``` #### PATCH /seo **Update SEO settings** Update store SEO settings Required scopes: settings.write, settings.* Parameters: - title: string - SEO title - description: string - Meta description - keywords: string - Meta keywords Example: ```javascript fetch(baseUrl + '/settings/seo', { method: 'PATCH', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ title: 'My Store - Premium Products', description: 'Shop the best products online' }) }) ``` #### PATCH /notifications **Update notifications** Update store notification settings Required scopes: settings.write, settings.* Parameters: - orderEmail: boolean - Email notifications for orders - orderSms: boolean - SMS notifications for orders - lowStockEmail: boolean - Email for low stock alerts Example: ```javascript fetch(baseUrl + '/settings/notifications', { method: 'PATCH', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ orderEmail: true, orderSms: true }) }) ``` ### Shipping Base path: /api/v1/dashboard/:storeId/shipping #### GET /couriers **List available couriers** Get list of available shipping couriers Required scopes: shipping.read, shipping.* Example: ```javascript fetch(baseUrl + '/shipping/couriers', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### GET /orders/:orderId **Get shipping info for order** Get shipping status and tracking info for an order Required scopes: orders.read, shipping.read Parameters: - orderId: string (required) - Order ID Example: ```javascript fetch(baseUrl + '/shipping/orders/507f1f77bcf86cd799439011', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST /labels **Create shipping label** Create a shipping label for an order Required scopes: shipping.write, shipping.* Parameters: - orderId: string (required) - Order ID - carrierId: string (required) - Carrier/courier ID - serviceType: string - Service type (express, economy) - weight: number - Package weight in kg - dimensions: object - Package dimensions {length, width, height} Example: ```javascript fetch(baseUrl + '/shipping/labels', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ orderId: '507f1f77bcf86cd799439011', carrierId: 'aramex', serviceType: 'express' }) }) ``` #### GET /addresses **Get store addresses** Get store shipping and return addresses Required scopes: shipping.read, shipping.* Example: ```javascript fetch(baseUrl + '/shipping/addresses', { headers: { 'X-API-Key': 'sk_live_xxxxx' } }) ``` #### POST /addresses **Add shipping address** Add a new store shipping address Required scopes: shipping.write, shipping.* Parameters: - name: string (required) - Address name/label - address: string (required) - Street address - city: string (required) - City - country: string (required) - Country code - postalCode: string - Postal code - phone: string - Phone number - isDefault: boolean [default: false] - Set as default address Example: ```javascript fetch(baseUrl + '/shipping/addresses', { method: 'POST', headers: { 'X-API-Key': 'sk_live_xxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Main Warehouse', address: '123 Main St', city: 'Riyadh', country: 'SA', isDefault: true }) }) ``` ### Storefront Base path: /api/v1/dashboard/:storeId/storefront #### GET /config **Get storefront config** Read store design config: name, theme colors, header settings, menus, social links. Required scopes: pages.view, pages.*, design.read, design.* #### PATCH /theme **Update theme colors** Update store theme colors and/or page templates (product, cart). Required scopes: pages.edit, pages.*, design.write, design.* Parameters: - colors: object - Color map, e.g. {primaryColor:"#1E4A7A", accentColor:"#2F6FAC"} - pageTheme: object - Page template overrides, e.g. {product:"...", cart:"..."} #### PATCH /seo **Update SEO** Update store-level or page-level SEO (title, description, keywords, ogImage). Required scopes: pages.edit, pages.*, design.write, design.* Parameters: - scope: string [store|page] [default: store] - SEO scope - pageName: string - Page name (when scope=page) - seo: object (required) - {title, description, keywords, ogImage} #### GET /page **Get full page snapshot** One-call snapshot of a page: store config, active version, ordered sections with their current values, available section themes, and custom components. Use this first to understand the page before editing. Required scopes: pages.view, pages.*, design.read, design.* Parameters: - page: string [default: home] - Page name #### GET /sections **List page sections** List the sections on a page in display order (top to bottom). Required scopes: pages.view, pages.*, design.read, design.* Parameters: - page: string [default: home] - Page name #### GET /sections/:sectionName **Read a section** Read a section's data-inputs and current values. Required scopes: pages.view, pages.*, design.read, design.* Parameters: - sectionName: string (required) - Section name, e.g. "products" or "hero" - page: string [default: home] - Page name #### PATCH /sections/:sectionName **Edit a section** Set data-input values for a section (e.g. title, selected products, image). Creates the section data if missing. Required scopes: pages.edit, pages.*, design.write, design.* Parameters: - sectionName: string (required) - Section name - page: string [default: home] - Page name - inputs: object (required) - Field map to set, e.g. {sectionTitle:"عروض", products:{search:{products:["id1","id2"]}}} #### POST /sections/reorder **Move/reorder sections** Reorder the sections on a page. Provide the full list of section names in the desired top-to-bottom order. Required scopes: pages.edit, pages.*, design.write, design.* Parameters: - page: string [default: home] - Page name - order: array (required) - Section names in display order, e.g. ["hero","products","features"] #### GET /versions **List page versions** List the available versions of a page (A/B variants, drafts). Required scopes: pages.view, pages.*, design.read, design.* Parameters: - page: string [default: home] - Page name #### POST /versions **Manage page versions** Create, duplicate, or activate a page version. Required scopes: pages.edit, pages.*, design.write, design.* Parameters: - action: string (required) [create|setActive|duplicate|list] - Version action - page: string [default: home] - Page name - versionId: string - Target version id - versionName: string - Display name (for create) - copyFrom: string - Source version id to clone from #### GET /section-themes **List section themes** List section themes available to the store (custom + global presets). Required scopes: pages.view, pages.*, design.read, design.* #### POST /section-themes **Create/update a section theme** Create or update a custom section theme (a compiled visual wrapper). To scope a theme to one section type (e.g. a custom look just for the products section), set sectionType to that section name — it then appears only for that section type, not as a generic theme. Required scopes: pages.edit, pages.*, design.write, design.* Parameters: - name: string (required) - Unique theme id (slug) - displayName: string - Human-readable name - category: string - Theme category (grouping label) - sectionType: string [default: *] - Section type this theme applies to, e.g. "products" to scope it to product sections, or "*" for any section - source: string (required) - Theme JSX/source - previewCss: string - Preview CSS #### DELETE /section-themes/:name **Delete a section theme** Deactivate a custom section theme. Required scopes: pages.edit, pages.*, design.write, design.* Parameters: - name: string (required) - Theme id #### GET /components **List custom sections** List the store's custom section components and the allowed component names. Required scopes: pages.view, pages.*, design.read, design.* #### POST /components **Create a custom section** Create or update a custom section component (JSX source, compiled in the browser). componentName must be one of the allowed names returned by listComponents. Required scopes: pages.edit, pages.*, design.write, design.* Parameters: - componentName: string (required) - Allowed component name (e.g. banner, products, footer, custom-code) - source: string (required) - JSX source for the component #### DELETE /components/:componentName **Delete a custom section** Deactivate a custom section component (revert to the default). Required scopes: pages.edit, pages.*, design.write, design.* Parameters: - componentName: string (required) - Component name ### Apps & OAuth Base path: /api/v1/apps #### GET /oauth/authorize **Authorization request** Initiate OAuth authorization flow Parameters: - client_id: string (required) - Your application client ID - redirect_uri: string (required) - Callback URL - scope: string (required) - Space-separated list of scopes - state: string (required) - Random state for CSRF protection - store_id: string - Pre-select store (optional) #### POST /oauth/token **Exchange code for token** Exchange authorization code for access token Parameters: - grant_type: string (required) - Grant type - code: string (required) - Authorization code (for authorization_code grant) - client_id: string (required) - Your client ID - client_secret: string (required) - Your client secret - redirect_uri: string (required) - Same redirect_uri used in authorize - refresh_token: string - Refresh token (for refresh_token grant) #### POST /oauth/revoke **Revoke token** Revoke an access or refresh token Parameters: - token: string (required) - Token to revoke - token_type_hint: string - Type of token - client_id: string (required) - Your client ID - client_secret: string (required) - Your client secret --- For more information, visit https://00pays.com