API Documentation

Seller API pagination and filters update

Seller-facing list endpoints keep backward compatibility. Old requests without query parameters still work. New clients may request larger paginated slices where supported.

Complete REST API documentation.

POST /auth/api-key/create

Exchange a raw seller API key for a short-lived JWT access token. Use this endpoint before any protected API method.


curl -X POST https://api.softstore.app/api/v1/auth/api-key/create \
-H "X-API-KEY: YOUR_RAW_SELLER_API_KEY" \
-H "Content-Type: application/json" \
-d "{}"
Response Schema
access_token string
expires_in integer
Error Responses

{
    "status": "error",
    "message": "error api key"
}

Invalid raw API keys return HTTP 401 with message: "error api key" Missing X-API-KEY returns message: "API key required". Protected endpoints without JWT return message: "Authorization header required".

POST /products

Request Overview

This endpoint allows sellers to create a new product or service offer in their inventory. The offer will be attached to the authenticated seller account.

Important: Product/service name and UUID must be unique per seller account. The system automatically validates category existence and category type, product quantity, pricing limits and feature formatting. Services use the same order, payment, chat, moderation and seller flows as products.

Request Parameters

Parameter Type Required Description
id_categories integer Yes Existing active category identifier. Category catalog_type decides whether the offer is a product or service.
id_sup_categories integer|null Only for services Active selectable service subcategory from /products/categories. Must be omitted or null for normal product categories.
type string No Optional client hint: product or service. If provided, it must match the selected category type.
name string Yes Product title (3-255 chars)
meta_title string Yes SEO meta title
meta_description string Yes SEO meta description
ru_title string No Optional Russian product title. Used on softstore.app when lang=ru; falls back to meta_title when empty. Must be unique per seller when provided.
ru_description string No Optional Russian product description. Used on softstore.app when lang=ru; falls back to meta_description when empty.
tags string Yes Comma-separated tags list
text_page string Yes Full English product page text (minimum 10 chars). Used by default and when lang=en.
ru_text_page string No Optional Russian product page text. Used on softstore.app when lang=ru; falls back to text_page when empty.
price integer Yes Product price (1 - 9,999,999)
count integer Yes Available stock quantity
uuid string Yes External product identifier (must be unique)
features string Yes Minimum 3 comma-separated features
discount integer No Optional product discount
opt_price string No Bulk discount percentages, comma-separated integers. Example: 5,10,20. Max 10 levels, max discount 90%.
opt_count string No Bulk quantity thresholds matching opt_price. Example: 10,100,200.
api_key string No Optional external API integration key
automated_message string No Optional automated message sent to the buyer in the order chat after purchase. Maximum 1000 characters.
special_offer string No Comma-separated product IDs for the public Special offer block. Maximum 3 products, same seller only, no self-reference. Categories may differ.
comment_status integer No Set 1 when buyer comment is required during checkout. Default: 0.
comment_placeholder string Conditional Label text above the checkout comment input. Required when comment_status=1. Max 300 chars, no HTML/script/control chars.
comment_input_placeholder string Conditional Placeholder inside the checkout comment input. Required when comment_status=1. Max 100 chars, no HTML/script/control chars.
gift_available integer No Set 1 to allow Gift creation for this product. Default: 0.
regexstringNoOptional strict buyer-comment validation: email, url, int, phone, or a validated custom regex (max 200 chars). Invalid or unsafe expressions reject product creation.

Response Parameters

Field Type Description
status string Response status
message string Success confirmation message
id string Generated internal product ID

Validation Rules

  • Category ID must exist in available categories list
  • Product name must be unique
  • UUID must be unique
  • Features field requires minimum 3 values
  • Price cannot be less than 1
  • Stock count cannot be negative
  • Text description must contain at least 10 characters
  • automated_message is optional and cannot exceed 1000 characters
  • special_offer is optional, accepts up to 3 comma-separated product IDs, and all referenced products must belong to the same seller

Request Example


curl -X POST https://api.softstore.app/api/v1/products \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
    "id_categories": 1,
    "name": "Windows 11 Pro Key",
    "meta_title": "Windows License",
    "meta_description": "Official activation key",
    "ru_title": "Лицензия Windows",
    "ru_description": "Официальный ключ активации",
    "tags": "windows,key,microsoft",
    "text_page": "Official Windows activation key with secure delivery after successful payment.",
    "ru_text_page": "Официальный ключ активации Windows с безопасной выдачей после успешной оплаты.",
    "price": 500,
    "count": 100,
    "uuid": "ext-123456",
    "features": "Lifetime activation,Instant delivery,Official key",
    "automated_message": "Thank you for your order. Delivery instructions will be sent here automatically.",
    "special_offer": "6a8977d9d7f8d,6a8977d9d7f87"
}'

Service example:


curl -X POST https://api.softstore.app/api/v1/products \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
    "id_categories": 702,
    "id_sup_categories": 6,
    "type": "service",
    "name": "API integration setup",
    "meta_title": "API integration setup",
    "meta_description": "Service offer for API integration setup",
    "tags": "api,integration,service",
    "text_page": "Describe deliverables, terms, warranty and communication flow in English.",
    "ru_text_page": "Опишите состав услуги, условия, гарантию и порядок общения на русском языке.",
    "price": 15000,
    "count": 5,
    "uuid": "service-api-setup-001",
    "features": "Scope agreed before start,Order chat support,Delivery through SoftStore"
}'

$response = $api->createProduct([
    'id_categories' => $categoryId,
    'name' => 'Test Product ' . rand(1000,9999),
    'meta_title' => 'Test Meta Title',
    'meta_description' => 'Test Meta Description',
    'tags' => 'test,api,product',
    'text_page' => 'This is a test product description',
    'price' => rand(100,1000),
    'count' => rand(1,1000),
    'uuid' => 'ext-' . uniqid(),
    'features' => 'Feature 1,Feature 2,Feature 3',
    'automated_message' => 'Thank you for your order. Delivery instructions will be sent here automatically.'
]);

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/products',
    {
        method: 'POST',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            id_categories: 1,
            name: "Windows 11 Pro Key",
            meta_title: "Windows License",
            meta_description: "Official key",
            tags: "windows,key",
            text_page: "Official product description",
            price: 500,
            count: 100,
            uuid: "ext-123456",
            features: "Feature 1,Feature 2,Feature 3",
            automated_message: "Thank you for your order. Delivery instructions will be sent here automatically."
        })
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "message": "Product created",
        "id": "69f8bd078449b",
        "type": "product"
    }
}

Error Responses


{
    "status": "error",
    "message": "Field 'name' is required"
}

{
    "status": "error",
    "message": "Product with this UUID already exists"
}

{
    "status": "error",
    "message": "Invalid category id"
}
POST /products/update/{id}

Request Overview

This endpoint updates an existing product that belongs to the authenticated seller. Only the product owner can update product data.

Important: Some fields trigger product moderation after update. Product status may be changed to wait automatically.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
Accept: application/json

URL Parameters

Parameter Type Required Description
id string Yes Product internal ID

Fields Without Moderation

Updating these fields does not trigger moderation.

Field Type Description
price integer Product price
discount integer Product discount percentage
opt_price string Bulk discount percentages, comma-separated. Empty value removes bulk discounts.
opt_count string Bulk quantity thresholds, comma-separated. Must match opt_price count.
count integer Available stock quantity
status string Status "active" or "off"
api_key string External API integration key
api_url string External API URL
automated_message string Optional automated order chat message, up to 1000 characters
special_offer string Optional comma-separated product IDs for Special offer. Maximum 3 products, same seller only, does not trigger repeat moderation by itself.
comment_status integer (0 or 1) Require buyer information during checkout.
comment_placeholder string Label above the buyer information field, maximum 300 characters.
comment_input_placeholder string Placeholder inside the buyer information field, maximum 100 characters.
gift_available integer (0 or 1) Allow buyers to purchase a Gift code for this product.
regexstringOptional strict buyer-comment expression. Changing this field alone does not trigger repeat moderation.

Fields That Trigger Moderation

Updating these fields will automatically send the product back to moderation.

Field Type Description
name string Product name
meta_title string SEO title
meta_description string SEO description
ru_title string Optional Russian title for lang=ru
ru_description string Optional Russian description for lang=ru
tags string Product tags
text_page string English product page text
ru_text_page string Optional Russian product page text for lang=ru
uuid string External product UUID
features string Comma-separated product features
id_categories integer Product category ID

Restricted Fields

The following fields cannot be updated:
  • rating
  • status_moderation

Request Example


curl -X POST https://api.softstore.app/api/v1/products/update/69f46db161e76 \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
    "price": 999,
    "discount": 15,
    "count": 200,
    "api_key": "new-api-key",
    "api_url": "https://example.com/api",
    "automated_message": "Updated automated order chat message.",
    "special_offer": "6a8977d9d7f8d,6a8977d9d7f87",
    "comment_status": 1,
    "comment_placeholder": "Your account login",
    "comment_input_placeholder": "login, email or account ID",
    "gift_available": 1,
    "name": "Updated Product Name",
    "ru_title": "Обновленное название товара",
    "ru_description": "Обновленное краткое описание товара",
    "text_page": "Updated English product page text",
    "ru_text_page": "Обновленный русский текст страницы товара",
    "tags": "updated,test,product",
    "features": "Feature A,Feature B,Feature C",
    "id_categories": 8
}'

$response = $api->updateProduct('69f46db161e76', [

    'price' => rand(100,999),
    'discount' => rand(0,30),
    'count' => rand(1,500),
    'api_key' => 'new-api-key',
    'api_url' => 'https://example.com/api',
    'automated_message' => 'Updated automated order chat message.',

    'name' => 'Updated Product',
    'text_page' => 'Updated description',
    'tags' => 'update,test',
    'features' => 'Feature 1,Feature 2,Feature 3',
    'id_categories' => 8
]);

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/products/update/69f46db161e76',
    {
        method: 'POST',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            price: 999,
            discount: 15,
            count: 300,
            automated_message: "Updated automated order chat message.",
            name: "Updated Product",
            text_page: "Updated product description",
            tags: "update,test",
            features: "Feature 1,Feature 2,Feature 3"
        })
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "message": "Product updated",
        "moderation": true
    }
}

Error Responses


{
    "status": "error",
    "message": "Product not found or access denied"
}

{
    "status": "error",
    "message": "Invalid price"
}

{
    "status": "error",
    "message": "UUID already exists"
}

{
    "status": "error",
    "message": "No fields to update"
}
DELETE /products/{id}

Request Overview

This endpoint permanently deletes an existing product from the authenticated seller inventory.

Warning: Product deletion is permanent and cannot be undone.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

URL Parameters

Parameter Type Required Description
id string Yes Internal product ID returned after product creation

Response Parameters

Field Type Description
status string Response status
message string Deletion confirmation message

Validation Rules

  • User must be authenticated via JWT token
  • Product must exist
  • Product must belong to authenticated seller
  • Deleted products cannot be restored

Request Example


curl -X DELETE https://api.softstore.app/api/v1/products/69f8bd078449b \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

$productId = "69f8bd078449b";

$response = $api->deleteProduct($productId);

print_r($response);

const productId = "69f8bd078449b";

const response = await fetch(
    `https://api.softstore.app/api/v1/products/${productId}`,
    {
        method: 'DELETE',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "message": "Product deleted"
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}
 
{
    "status": "error",
    "message": "Product not found"
}

{
    "status": "error",
    "message": "Delete failed or access denied"
}
GET /products/info/{id}

Request Overview

Retrieve full information about a specific product that belongs to the authenticated seller account.

Important: The system returns product details only if the product exists and belongs to the authenticated seller.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

URL Parameters

Parameter Type Required Description
id string Yes Internal product identifier

Response Parameters

Field Type Description
status string Response status
product.id string Internal product ID
product.name string Product name
product.price integer Product price
product.count integer Available stock quantity
product.discount integer Applied discount percentage
product.uuid string External product UUID
product.status_moderation string Moderation status
product.created_at datetime Creation date

Validation Rules

  • User must be authenticated
  • Product must exist
  • Product must belong to authenticated seller
  • Invalid product ID returns error

Request Example


curl -X GET https://api.softstore.app/api/v1/products/info/69f8bd078449b \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

$productId = "69f8bd078449b";

$response = $api->getProduct($productId);

print_r($response);

const productId = "69f8bd078449b";

const response = await fetch(
    `https://api.softstore.app/api/v1/products/info/${productId}`,
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "product": {
            "id": "69f8bd078449b",
            "name": "Windows 11 Pro Key",
            "price": 500,
            "count": 100,
            "discount": 10,
            "uuid": "ext-123456",
            "status_moderation": "approved",
            "created_at": "2026-05-05 12:30:00"
        }
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Product not found"
}

{
    "status": "error",
    "message": "Access denied"
}
GET /products

Request Overview

Returns a paginated list of products that belong to the authenticated seller account.

Important: This endpoint supports pagination and filtering. Use query parameters to optimize large product inventories.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

Query Parameters

Parameter Type Required Description
page integer No Pagination page number (default: 1)
limit integer No Items per page. Allowed values: 30, 50, 500. Default: 30
availability string No Filter by product availability: all, on / enabled (status=active), off / disabled (not active). Default: all
category integer No Filter by category ID
sort string No Sort field: default, price, created, quantity, sales, discount, opt
direction string No Sort direction: high_to_low or low_to_high
include_category_counts integer No Set to 1 to include category_counts for category dropdowns
search string No Search products by name

Response Parameters

Field Type Description
status string Response status
products array List of seller products
products[].id string Product internal ID
products[].name string Product title
products[].price integer Product price
products[].count integer Available quantity
products[].status_moderation string Moderation status
pagination.total integer Total products count
pagination.page integer Current page
pagination.limit integer Current limit

Validation Rules

  • User must be authenticated
  • Page value must be greater than 0
  • Limit value must be within allowed range
  • Invalid filters may return empty result

Request Example


	curl -X GET "https://api.softstore.app/api/v1/products?page=1&limit=30&sort=price&direction=high_to_low&category=12&availability=on&include_category_counts=1" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

$response = $api->getProducts([
    'page' => 1,
    'limit' => 30,
    'sort' => 'price',
    'direction' => 'high_to_low',
    'category' => 12,
    'availability' => 'on',
    'include_category_counts' => 1
]);

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/products?page=1&limit=30&sort=price&direction=high_to_low&category=12&availability=on&include_category_counts=1',
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "products": [
            {
                "id": "69f8bd078449b",
                "name": "Windows 11 Pro Key",
                "price": 500,
                "count": 100,
                "status": "active",
                "status_moderation": "approved"
            }
        ],
        "pagination": {
            "total": 150,
            "page": 1,
            "limit": 20
        }
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Invalid pagination parameters"
}
GET /products/categories

Request Overview

This endpoint returns the full list of available product and service categories that sellers can use when creating or updating offers.

Important: Use category IDs from this endpoint when sending id_categories during product/service creation or update. Categories with catalog_type=service use the expanded RU/EN service taxonomy. Pass only a selectable child subcategories[].id as id_sup_categories. Deprecated umbrella categories, including freelancer-services, are not returned and must not be used in new integrations.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

Response Parameters

Field Type Description
status string Response status
data array Array of available categories
id integer Category internal identifier
name string Category title
slug string Category URL slug
name_en / slug_en string English taxonomy fallback fields for RU/EN interfaces
catalog_type string product or service. This is the source of truth for offer type.
has_subcategories integer 1 when sellers must choose a service subcategory
subcategories array Service subcategory tree with RU/EN titles, parent_id, is_new, is_selectable, status and sort order
status string Category status

Business Logic

  • Returns only active categories
  • Inactive categories may be hidden from sellers
  • Deprecated umbrella categories such as Freelancer Services are hidden from API, LK and public catalog
  • Category IDs are required for product/service creation
  • Service categories return a hierarchical taxonomy: group rows have is_selectable=0, leaf rows have is_selectable=1
  • Service creation/update requires a valid active selectable leaf subcategory ID
  • Normal products must omit service subcategory IDs
  • Use this endpoint before creating marketplace integrations

Request Example


curl -X GET https://api.softstore.app/api/v1/products/categories \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

$response = $api->getCategories();

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/products/categories',
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": [
        {
            "id": 1,
            "name": "Software Keys",
            "slug": "software-keys",
            "status": "active"
        },
        {
            "id": 2,
            "name": "Gaming Accounts",
            "slug": "gaming-accounts",
            "status": "active"
        },
        {
            "id": 3,
            "name": "Subscriptions",
            "slug": "subscriptions",
            "status": "active"
        }
    ]
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Categories not found"
}
POST /products/moderation

Request Overview

This endpoint sends an existing product to manual moderation. Uploading or replacing the product image also returns the product to pending moderation. After submitting, moderators will review product content, image, pricing, category selection and marketplace compliance.

Important: Products already under moderation may not be submitted again until the current review process is completed.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
Accept: application/json

Request Parameters

Parameter Type Required Description
id_product string Yes Internal product identifier

Response Parameters

Field Type Description
status string Response status
message string Moderation submission result
moderation_status string Current moderation state

Moderation Rules

  • Product must belong to authenticated seller
  • Product must exist
  • Product cannot already be under active moderation
  • A product must have an image before it can be sent to moderation
  • Uploading/replacing an image sets moderation back to pending
  • Moderators may reject invalid products
  • Rejected products can be fixed and resubmitted later

Request Example


curl -X POST https://api.softstore.app/api/v1/products/moderation \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
    "id_product": "69f8bd078449b"
}'

$response = $api->sendProductToModeration([
    'id_product' => '69f8bd078449b'
]);

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/products/moderation',
    {
        method: 'POST',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            id_product: "69f8bd078449b"
        })
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "message": "Product submitted for moderation",
        "moderation_status": "pending"
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Product not found"
}

{
    "status": "error",
    "message": "Product is already under moderation"
}

{
    "status": "error",
    "message": "Access denied"
}
GET /orders/statistics

Request Overview

Returns seller order statistics for a selected period ending at a selected date. The response is ready for dashboard charts and contains both aggregate metrics and daily series points.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

Query Parameters

Field Type Required Description
period string False day, week, month, or year. Default: day.
date string False Selected end date in YYYY-MM-DD format. Week/month/year ranges count backward from this date.

Request Example


curl -X GET "https://api.softstore.app/api/v1/orders/statistics?period=week&date=2026-08-10" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

Success Response


{
  "status": "success",
  "data": {
    "period": "week",
    "date": "2026-08-04",
    "date_to": "2026-08-10",
    "selected_date": "2026-08-10",
    "metrics": {
      "orders": 179,
      "paid_orders": 3,
      "unpaid_orders": 176,
      "revenue": 2461,
      "avg_check": 820.33,
      "conversion_percent": 1.68,
      "growth_percent": 100,
      "products": 39
    },
    "series": [
      {
        "date": "2026-08-07",
        "orders": 41,
        "paid_orders": 1,
        "revenue": 1890
      }
    ]
  }
}

Error Responses


{
  "status": "error",
  "message": "Unauthorized"
}

{
  "status": "error",
  "message": "Invalid date format. Use YYYY-MM-DD."
}
GET /orders

Request Overview

This endpoint returns the full order history for the authenticated seller. It allows sellers to monitor all purchases made for their products. Buyer email addresses are exposed only in seller webhook callback payloads after successful payment. Regular seller API responses and the seller dashboard do not expose buyer email addresses.

Important: Only orders related to the authenticated seller account will be returned.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

Request Body

Field Type Required Description
status string False Orders status: wait / paid / cancel / dispute
date string False Orders date Y-M-D

Response Parameters

Field Type Description
id_order string Unique order identifier
id_product string Purchased product ID
amount string Total order amount
status_order string Current order status (wait / paid / cancel / dispute)
data_create string Order creation date
time_create string Order creation time
count string Purchased quantity

Business Logic

  • Returns only seller-owned orders
  • Does not expose buyer email addresses in regular API responses
  • Buyer email is available in the seller webhook callback payload after successful payment
  • Requires valid JWT authorization
  • Orders are returned as full history list
  • Use /orders/info/{id} for detailed order information

Request Example


curl -X GET https://api.softstore.app/api/v1/orders \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

$response = $api->getOrders();

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/orders',
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": [
        {
            "id_order": "3fb0a629f15a0bdd7ce4b69f9a164911",
            "id_product": "69f362be33c2a",
            "amount": "9408",
            "status_order": "wait",
            "data_create": "2026-05-02",
            "time_create": "17:28:49",
            "count": "16"
        },
        {
            "id_order": "4b51c4d77809743fdd172713feb02300",
            "id_product": "777156470",
            "amount": "640",
            "status_order": "paid",
            "data_create": "2026-04-28",
            "time_create": "13:46:13",
            "count": "5"
        }
    ]
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}
GET /orders/info/{id}

Request Overview

This endpoint returns detailed information about a specific order. Sellers can only access orders that belong to their own account.

Important: If the order does not belong to the authenticated seller, access will be denied.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

Path Parameters

Parameter Type Required Description
id string Yes Unique order identifier

Response Parameters

Field Type Description
id string Internal database ID
title string Name product
id_user string Registered buyer ID (if available)
guest_id string Guest buyer identifier
buyer_type string Buyer type (guest / registered)
comment string Comment for order
id_product string Purchased product ID
id_seller string Seller identifier
id_order string Public order identifier
status_order string Order status
data_create string Order creation date
time_create string Order creation time
amount string Total payment amount
count string Purchased quantity
payment_system string Payment provider name

Business Logic

  • Seller can only access their own orders
  • Order must exist
  • Requires valid JWT token
  • Returns order payment and delivery metadata; buyer email is delivered through the payment webhook callback

Request Example


curl -X GET https://api.softstore.app/api/v1/orders/info/4b51c4d77809743fdd172713feb02300 \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

$response = $api->infoOrder(
    '4b51c4d77809743fdd172713feb02300'
);

print_r($response);

const orderId = "4b51c4d77809743fdd172713feb02300";

const response = await fetch(
    `https://api.softstore.app/api/v1/orders/info/${orderId}`,
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "id": "94",
        "id_user": "0",
        "title": "Test Name",
        "guest_id": "70df52e8ca9741105f5d3ccaee808edd",
        "buyer_type": "guest",
        "id_product": "777156470",
        "id_seller": "1774966755",
        "id_order": "4b51c4d77809743fdd172713feb02300",
        "email": "ads@frogs-wallet.biz",
        "status_order": "paid",
        "data_create": "2026-04-28",
        "time_create": "13:46:13",
        "amount": "640",
        "count": "5",
        "payment_system": "cyberpay"
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Order not found or access denied"
}
POST /orders/delivery/{token}

Overview

This endpoint allows sellers to deliver digital products after receiving a successful payment webhook notification.

Important: The {token} is automatically generated by SoftStore and included inside webhook notification payload.

Delivery Flow


1. Customer purchases product
↓
2. Payment completed
↓
3. SoftStore sends webhook to seller API
↓
4. Seller receives delivery_url
↓
5. Seller sends digital product to delivery_url
↓
6. Buyer receives product via email

Webhook Notification Example


{
  "id_order": "030a3c6f15f2744e58f2e24fd40d3466",
  "id_product": "69f36497dc78f",
  "email": "buyer@example.com",
  "comment": "buyer_login@example.com",
  "payment_status": "paid",
  "signature": "df595764abc185bbf31c5c6334cfade65379feb6",
  "delivery_url": "https://api.softstore.app/api/v1/orders/delivery/TOKEN",
  "token": "d487c01d834dcb296c4f7b5a02e0b0d9df320bb153778d6c20cd26e2c50b40bf"
}

Request Body

Field Type Required Description
text string Yes Product delivery message / activation key / credentials
download string (https url) No Optional download link for digital file delivery

Delivery Types

Text Delivery:
Product keys, credentials, license codes, instructions
Download Delivery:
Files, archives, software installers, ebooks etc.

Request Examples


curl -X POST \
https://api.softstore.app/api/v1/orders/delivery/TOKEN_HERE \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
  "text":"Windows 11 activation key: XXXXX-XXXXX",
  "download":"https://cdn.example.com/windows.zip"
}'

$response = $api->deliverOrder($token, [
    'text' => 'Windows license key: XXXXX',
    'download' => 'https://cdn.example.com/file.zip'
]);

print_r($response);

await fetch(deliveryUrl, {
    method: "POST",
    headers: {
        "Authorization": "Bearer YOUR_JWT_TOKEN",
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        text: "Your license key: XXXXX",
        download: "https://cdn.example.com/file.zip"
    })
});

Success Response


{
  "status": "success",
  "data": {
    "message": "Product delivered successfully",
    "id_order": "030a3c6f15f2744e58f2e24fd40d3466",
    "delivered": true
  }
}

Error Responses

HTTP Error Description
401 Unauthorized Invalid JWT token
404 Order not found Invalid delivery token
409 Order already delivered Product already sent
422 Invalid download URL Only HTTPS links allowed
GET /seller

Request Overview

This endpoint returns full information about the authenticated seller account. It allows marketplace sellers to retrieve profile information, financial balance, API settings, moderation status and public store details.

Important: This endpoint only returns data for the authenticated seller. JWT authorization is required.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

Response Parameters

Field Type Description
id integer Internal seller record ID
id_user integer Telegram/User account identifier
name string Store name
balance integer Current seller balance
img string Seller profile image URL
description string Store description
api_url string Connected external API URL
data_create string Account registration date
rating integer Seller marketplace rating
api_key string Seller API key
status_moderation integer Seller moderation status

Business Logic

  • JWT token must be valid
  • Seller account must exist
  • Only current authenticated seller data is returned
  • API key is returned for integration usage
  • Balance reflects current available funds

Request Example


curl -X GET https://api.softstore.app/api/v1/seller \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

<?php

require_once "sellerApi.php";

$api = new SellerApi(
    'https://api.softstore.app/api/v1',
    'YOUR_API_KEY'
);

// create JWT token
$api->createApiKey();

// get seller info
$response = $api->getSellerInfo();

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/seller',
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "id": 1,
        "id_user": 1774966755,
        "name": "My shop 777",
        "balance": 19056,
        "img": "https://img.softstore.app/uploads/example.png",
        "description": "Best shop ever 777",
        "api_url": "https://api.soft-shop.com",
        "data_create": "10.04.2026",
        "rating": 0,
        "api_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "status_moderation": 0
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Seller not found"
}
POST /seller/profile

Request Overview

This endpoint allows sellers to update their store profile information. Only specific fields are allowed for editing. The system validates all incoming data before saving changes.

Important: Only name, description and api_url fields can be updated.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
Accept: application/json

Allowed Request Parameters

Parameter Type Required Description
name string No Store name (3-100 characters)
description string No Store description (10-1000 characters)
api_url string No External API URL

Validation Rules

  • Name must contain 3 to 100 characters
  • Name cannot contain dangerous symbols
  • Description must contain 10 to 1000 characters
  • HTML/script tags are automatically sanitized
  • API URL must be valid
  • Unknown fields are rejected
  • Empty update requests are rejected

Restricted Fields

The following fields cannot be updated through this endpoint:
  • balance
  • rating
  • api_key
  • status_moderation
  • id_user

Request Example


curl -X POST https://api.softstore.app/api/v1/seller/profile \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
    "name": "My New Store Name",
    "description": "Updated store description for customers",
    "api_url": "https://example-api.com"
}'

<?php

require_once "sellerApi.php";

$api = new SellerApi(
    'https://api.softstore.app/api/v1',
    'YOUR_API_KEY'
);

// create JWT
$api->createApiKey();

// update seller profile
$response = $api->updateSellerProfile([
    'name' => 'Updated Store Name',
    'description' => 'Updated description text',
    'api_url' => 'https://example-api.com'
]);

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/seller/profile',
    {
        method: 'POST',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            name: "Updated Store Name",
            description: "Updated description text",
            api_url: "https://example-api.com"
        })
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "id": 1,
        "name": "Updated Store Name",
        "description": "Updated description text",
        "api_url": "https://example-api.com"
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Invalid JSON"
}

{
    "status": "error",
    "message": "Name must be between 3 and 100 characters"
}

{
    "status": "error",
    "message": "Description too short (min 10)"
}

{
    "status": "error",
    "message": "Invalid API URL"
}

{
    "status": "error",
    "message": "Field 'balance' is not allowed"
}

{
    "status": "error",
    "message": "No valid data to update"
}

{
    "status": "error",
    "message": "Profile not updated"
}
POST /products/img

Request Overview

This backward-compatible endpoint replaces the primary product image. Images are uploaded using multipart/form-data. The image will be linked to the authenticated seller product.

Important: Product must belong to the authenticated seller. Only valid image formats are accepted.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: multipart/form-data

Form Data Parameters

Parameter Type Required Description
img file Yes Product image file
id_product string Yes Product internal ID

Validation Rules

  • JWT token must be valid
  • Product must exist
  • Product must belong to authenticated seller
  • Image file is required
  • Only image MIME types are accepted
  • Invalid uploads are rejected

Request Example


curl -X POST https://api.softstore.app/api/v1/products/img \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-F "img=@product-image.png" \
-F "id_product=69f8bd078449b"

<?php

require_once "sellerApi.php";

$api = new SellerApi(
    'https://api.softstore.app/api/v1',
    'YOUR_API_KEY'
);

// create JWT
$api->createApiKey();

// upload image
$response = $api->uploadProductImage(
    '69f8bd078449b',
    '/home/user/product-image.png'
);

print_r($response);

const formData = new FormData();

formData.append('img', fileInput.files[0]);
formData.append('id_product', '69f8bd078449b');

const response = await fetch(
    'https://api.softstore.app/api/v1/products/img',
    {
        method: 'POST',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN'
        },
        body: formData
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "message": "Product image uploaded",
        "url": "https://img.softstore.app/uploads/products/example.png"
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Image file required"
}

{
    "status": "error",
    "message": "Product not found or access denied"
}

{
    "status": "error",
    "message": "Invalid image format"
}
POST /seller/img

Request Overview

This endpoint allows sellers to upload or update their profile image. The uploaded image becomes the public avatar/logo of the seller store.

Important: Only authenticated sellers can upload profile images. Previous image may be replaced automatically.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: multipart/form-data

Form Data Parameters

Parameter Type Required Description
img file Yes Seller profile image file

Validation Rules

  • JWT token must be valid
  • Image file is required
  • Only valid image formats are allowed
  • Invalid uploads will be rejected
  • Old profile image may be replaced automatically

Request Example


curl -X POST https://api.softstore.app/api/v1/seller/img \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-F "img=@seller-avatar.png"

<?php

require_once "sellerApi.php";

$api = new SellerApi(
    'https://api.softstore.app/api/v1',
    'YOUR_API_KEY'
);

// create JWT
$api->createApiKey();

// upload seller image
$response = $api->uploadSellerImage(
    '/home/user/seller-avatar.png'
);

print_r($response);

const formData = new FormData();

formData.append('img', fileInput.files[0]);

const response = await fetch(
    'https://api.softstore.app/api/v1/seller/img',
    {
        method: 'POST',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN'
        },
        body: formData
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "message": "Profile image uploaded",
        "url": "https://img.softstore.app/uploads/sellers/avatar.png"
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Image file required"
}

{
    "status": "error",
    "message": "Invalid image format"
}

{
    "status": "error",
    "message": "Upload failed"
}
POST /payout

Request Overview

Create a withdrawal request from seller internal balance. This endpoint requires Google Authenticator OTP verification.

Important: Funds are immediately reserved after successful payout creation.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
Accept: application/json

Request Parameters

Parameter Type Required Description
amount integer Yes Payout amount (min: 1000)
payment_system string Yes usdt / card / payment_account
wallet string Yes Wallet address / card number / bank account
cod string Yes 6-digit Google Authenticator OTP code

Validation Rules

  • JWT token must be valid
  • Seller account must exist
  • Amount must be between 1000 and 1000000
  • Seller balance must be sufficient
  • OTP code must be valid
  • Only supported payout systems allowed

Request Example


curl -X POST https://api.softstore.app/api/v1/payout \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
    "amount": 5000,
    "payment_system": "usdt",
    "wallet": "TRC20_WALLET_ADDRESS",
    "cod": "123456"
}'

<?php

$response = file_get_contents(
    'https://api.softstore.app/api/v1/payout',
    false,
    stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => [
                'Authorization: Bearer YOUR_JWT_TOKEN',
                'Content-Type: application/json'
            ],
            'content' => json_encode([
                'amount' => 5000,
                'payment_system' => 'usdt',
                'wallet' => 'TRC20_WALLET_ADDRESS',
                'cod' => '123456'
            ])
        ]
    ])
);

echo $response;

const response = await fetch(
    'https://api.softstore.app/api/v1/payout',
    {
        method: 'POST',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            amount: 5000,
            payment_system: 'usdt',
            wallet: 'TRC20_WALLET_ADDRESS',
            cod: '123456'
        })
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "id_order": "6fa81a21b1d44e9"
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Invalid OTP code"
}

{
    "status": "error",
    "message": "Insufficient balance"
}
GET /payout/history

Request Overview

Retrieve full payout history for the authenticated seller. Returns withdrawal transactions created from seller balance.

Important: Only payouts created by the authenticated seller are returned.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

Request Parameters

Parameter Type Required Description
No This endpoint does not require request body parameters

Response Parameters

Field Type Description
id_order string Payout transaction identifier
type string Transaction type (out)
amount integer Payout amount
status string Payout processing status
payment_system string Selected payout payment method
date_create date Creation date
time_create time Creation time

Validation Rules

  • User must be authenticated
  • Seller account must exist
  • Only own payout history is accessible

Request Example


curl -X GET https://api.softstore.app/api/v1/payout/history \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

<?php

require_once "sellerApi.php";

$api = new SellerApi(
    "https://api.softstore.app/api/v1",
    "YOUR_API_KEY"
);

// create JWT
$api->createApiKey();

// get payout history
$response = $api->getPayoutHistory();

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/payout/history',
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": [
        {
            "id_order": "6fa81a21b1d44e9",
            "type": "out",
            "amount": 5000,
            "status": "wait",
            "payment_system": "usdt",
            "date_create": "2026-05-17",
            "time_create": "14:25:11"
        }
    ]
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Seller not found"
}
POST /check/gift

Request Overview

Returns information about one Gift code by its exact key. The authenticated seller can access a Gift only when its product belongs to that seller.

Security: Bearer JWT is required. Unknown codes and codes belonging to another seller both return the same 404 Gift not found. Listing or searching by order, email, date, product, or activation status is not supported.

JSON Body

NameTypeRequiredDescription
keystringYesComplete Gift key in format GIFT-0123456789ABCDEF.

Example

curl -X POST https://api.softstore.app/api/v1/check/gift \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"key":"GIFT-0123456789ABCDEF"}'

Success Response

{
  "status": "success",
  "data": {
    "id_order": "dc31f111000000000000000000000000",
    "payment_status": "paid",
    "id_product": "6a9335a225037",
    "title": "App Store & iTunes (RU)",
    "gift_status": "active",
    "is_activated": false,
    "created_at": "2026-09-14 08:00:00",
    "activated_at": null,
    "count": 1
  }
}

Errors

  • 401 — missing or expired JWT.
  • 422 — key parameter is missing.
  • 404 — Gift is unknown, malformed, or belongs to another seller.
  • 429 — rate limit exceeded.
GET /chat

Request Overview

Returns a list of chats that belong to the authenticated seller. Each chat is linked to a specific order.

Important: Only chats related to orders owned by the authenticated seller are returned.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

Response Parameters

Field Type Description
id string Chat ID
id_order string Order identifier
title string Chat title
status_order string Current order status
amount float Order amount

Request Example


curl -X GET https://api.softstore.app/api/v1/chat \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

$response = $api->getChats();

print_r($response);

const response = await fetch(
    'https://api.softstore.app/api/v1/chat',
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": [
        {
            "id": 15,
            "id_order": "f87663f1ce0764d4c50c17bc39d536d9",
            "title": "Order# f87663f1ce0764d4c50c17bc39d536d9",
            "status_order": "paid",
            "amount": 49.99
        }
    ]
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}
GET /chat/info/{id}

Request Overview

Returns detailed information about a specific chat. The chat must belong to an order owned by the authenticated seller.

Important: Access is restricted to the seller who owns the related order. Requests for foreign chats will return an access denied error.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

URL Parameters

Parameter Type Required Description
id string Yes Chat identifier

Response Parameters

Field Type Description
id string Chat ID
id_order string Associated order identifier
title string Chat title
data_create date Creation date
time_create time Creation time

Validation Rules

  • User must be authenticated using a valid JWT token
  • Chat must exist
  • Chat must belong to the authenticated seller
  • Invalid chat ID returns an error response

Request Example


curl -X GET https://api.softstore.app/api/v1/chat/info/f87663f1ce0764d4c50c17bc39d536d9 \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

$chatId = 15;

$response = $api->getChatInfo($chatId);

print_r($response);

const chatId = 15;

const response = await fetch(
    `https://api.softstore.app/api/v1/chat/info/${chatId}`,
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "id": 15,
        "id_order": "f87663f1ce0764d4c50c17bc39d536d9",
        "title": "Order# f87663f1ce0764d4c50c17bc39d536d9",
        "data_create": "2026-06-12",
        "time_create": "15:10:22"
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Chat not found"
}

{
    "status": "error",
    "message": "Access denied"
}
GET /chat/messages/{id}

Request Overview

Returns the complete message history for a specific chat. Messages are returned in chronological order, starting from the oldest message.

Important: Only messages from chats associated with the authenticated seller's orders can be accessed.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json

URL Parameters

Parameter Type Required Description
id string Yes Chat identifier

Response Parameters

Field Type Description
id integer Message ID
id_chat string Chat identifier
id_user integer Message author ID
type_user string Message author role (buyer, seller, admin)
message string Message text
data_create date Message creation date
time_create time Message creation time

Validation Rules

  • User must be authenticated using a valid JWT token
  • Chat must exist
  • Chat must belong to the authenticated seller
  • Maximum of 100 messages are returned per request
  • Messages are sorted in ascending order by message ID

Request Example


curl -X GET https://api.softstore.app/api/v1/chat/messages/f87663f1ce0764d4c50c17bc39d536d9 \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"

$chatId = "f87663f1ce0764d4c50c17bc39d536d9";

$response = $api->getChatMessages($chatId);

print_r($response);

const chatId = "f87663f1ce0764d4c50c17bc39d536d9";

const response = await fetch(
    `https://api.softstore.app/api/v1/chat/messages/${chatId}`,
    {
        method: 'GET',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            Accept: 'application/json'
        }
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": [
        {
            "id": 1,
            "id_chat": "f87663f1ce0764d4c50c17bc39d536d9",
            "id_user": 55,
            "type_user": "seller",
            "message": "Hello, your order has been processed.",
            "data_create": "2026-06-12",
            "time_create": "15:10:22"
        },
        {
            "id": 2,
            "id_chat": "f87663f1ce0764d4c50c17bc39d536d9",
            "id_user": 101,
            "type_user": "buyer",
            "message": "Thank you for the update.",
            "data_create": "2026-06-12",
            "time_create": "15:11:08"
        }
    ]
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Chat not found"
}

{
    "status": "error",
    "message": "Access denied"
}
POST /chat/send/{id}

Request Overview

Sends a new message to an existing chat. The authenticated seller can send messages only to chats associated with their own orders.

Important: Messages may be checked by the platform moderation system. Duplicate messages are automatically rejected.

Headers


Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
Accept: application/json

URL Parameters

Parameter Type Required Description
id string Yes Chat identifier

Request Body

Field Type Required Description
message string Yes Message text to send

Validation Rules

  • User must be authenticated using a valid JWT token
  • Chat must exist
  • Chat must belong to the authenticated seller
  • Message field is required
  • Empty messages are not allowed
  • Duplicate messages are automatically rejected
  • Platform moderation rules may apply

Request Example


curl -X POST https://api.softstore.app/api/v1/chat/send/f87663f1ce0764d4c50c17bc39d536d9 \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
    "message": "Hello buyer, your order has been delivered."
}'

$chatId = "f87663f1ce0764d4c50c17bc39d536d9";

$response = $api->sendChatMessage(
    $chatId,
    [
        'message' => 'Hello buyer, your order has been delivered.'
    ]
);

print_r($response);

const chatId = "f87663f1ce0764d4c50c17bc39d536d9";

const response = await fetch(
    `https://api.softstore.app/api/v1/chat/send/${chatId}`,
    {
        method: 'POST',
        headers: {
            Authorization: 'Bearer YOUR_JWT_TOKEN',
            'Content-Type': 'application/json',
            Accept: 'application/json'
        },
        body: JSON.stringify({
            message: 'Hello buyer, your order has been delivered.'
        })
    }
);

console.log(await response.json());

Success Response


{
    "status": "success",
    "data": {
        "message": "Message sent successfully"
    }
}

Error Responses


{
    "status": "error",
    "message": "Unauthorized"
}

{
    "status": "error",
    "message": "Chat not found"
}

{
    "status": "error",
    "message": "Access denied"
}

{
    "status": "error",
    "message": "Message is required"
}

{
    "status": "error",
    "message": "Duplicate message"
}

{
    "status": "error",
    "message": "The message did not pass moderation"
}
POST Seller Webhook Notifications

Overview

SoftStore automatically sends webhook notifications to your api_url after successful payment.

Configure your webhook URL via: POST /seller/profile

Incoming Webhook Payload

 
{
  "id_order": "030a3c6f15f2744e58f2e24fd40d3466",
  "id_product": "69f36497dc78f",
  "email": "buyer@example.com",
  "payment_status": "paid",
  "comment": "@login",
  "signature": "df595764abc185bbf31c5c6334cfade65379feb6",
  "delivery_url": "https://api.softstore.app/api/v1/orders/delivery/TOKEN",
  "token": "d487c01d834dcb296c4f7b5a02e0b0d9df320bb153778d6c20cd26e2c50b40bf"
}

Signature Verification

Signature formula:

The email field contains the buyer email address for this paid order. It is informational and is not included in signature generation, so existing webhook integrations remain compatible.

sha1( sha1(api_key) + id_order)

Webhook Verification Examples


$payload = json_decode(
    file_get_contents('php://input'),
    true
);

$apiKey = "YOUR_SECRET_API_KEY";

$expected = sha1(
    sha1($apiKey) . $payload['id_order']
);

if ($expected !== $payload['signature']) {
    http_response_code(403);
    exit('Invalid signature');
}

$deliveryUrl = $payload['delivery_url'];

echo "Webhook verified";

const crypto = require("crypto");

app.post("/webhook", (req, res) => {

    const payload = req.body;


     // sha1(apiKey)
        const hashedApiKey = crypto
            .createHash("sha1")
            .update(API_KEY)
            .digest("hex");

    const expected = crypto
        .createHash("sha1")
        .update(hashedApiKey + payload.id_order)
        .digest("hex");

    if (expected !== payload.signature) {
        return res.status(403).json({
            error: "Invalid signature"
        });
    }

    const deliveryUrl = payload.delivery_url;

    console.log("Valid webhook:", deliveryUrl);

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

Recommended Flow


Receive webhook
↓
Validate signature
↓
Get delivery_url
↓
Generate product/license/file
↓
Send product to delivery_url
↓
Customer receives order

Webhook Errors

Error Description
Invalid signature Webhook request is not trusted
Missing delivery_url Webhook payload corrupted
Product generation failed Seller internal delivery logic failed
POST Incoming Webhook Chat Message

Overview

SoftStore sends an HTTP callback to the seller api_url when a buyer writes a new message in a paid order chat. This lets sellers receive buyer questions and answer them through the Chat API.

Chat message webhooks are sent only to the seller of the related order. Seller, administrator and system messages do not trigger this callback.

Incoming Payload


{
  "type": "message",
  "id_chat": "030a3c6f15f2744e58f2e24fd40d3466",
  "text": "Hello. When will I receive my key?",
  "payment_status": "paid",
  "signature": "df595764abc185bbf31c5c6334cfade65379feb6"
}
Field Type Description
type string Always message for buyer chat message callbacks.
id_chat string Order ID connected to this chat. Use it as {id} for chat API methods.
text string Buyer message text, trimmed and limited to 1000 characters.
payment_status string Order payment status. Chat callbacks are sent for paid orders.
signature string Webhook signature used to verify the request.

Signature Verification


sha1( api_key + id_chat )
The callback body must be treated as untrusted input. Do not execute buyer text as commands, prompts, templates or code. Store and display it as plain text only.

Recommended Security Rules

  • Accept callbacks only from SoftStore server IP addresses when possible.
  • Validate signature before reading or acting on text.
  • Require type === "message" and payment_status === "paid".
  • Limit processing to text values from 1 to 1000 characters.
  • Strip HTML, control characters and invisible characters before displaying messages.
  • Do not pass buyer messages directly into AI agents, shell commands, SQL or internal tools.
  • Use idempotency on id_chat + text + signature to avoid duplicate processing.
  • Return HTTP 200 quickly; process long tasks asynchronously.

Reply to the Buyer


curl -X POST https://api.softstore.app/api/v1/auth/api-key/create \
  -H "X-API-KEY: RAW_SELLER_API_KEY"

curl -X POST https://api.softstore.app/api/v1/chat/send/030a3c6f15f2744e58f2e24fd40d3466 \
  -H "Authorization: Bearer JWT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Hello. Your order is being processed. I will send the key here shortly."
  }'

Webhook Handler Examples


<?php

$payload = json_decode(file_get_contents('php://input'), true);
$apiKey = 'RAW_SELLER_API_KEY';

if (($payload['type'] ?? '') !== 'message') {
    http_response_code(400);
    exit('Unsupported webhook type');
}

$expected = sha1($apiKey . $payload['id_chat']);

if (!hash_equals($expected, $payload['signature'] ?? '')) {
    http_response_code(403);
    exit('Invalid signature');
}

$text = trim((string)($payload['text'] ?? ''));

if ($text === '' || mb_strlen($text) > 1000) {
    http_response_code(422);
    exit('Invalid message text');
}

// Store or process the buyer message as plain text only.

$api = new SellerApi('https://api.softstore.app/api/v1', $apiKey);
$auth = $api->createApiKey();

if ($auth['status'] === 200) {
    $api->sendChatMessage($payload['id_chat'], [
        'message' => 'Hello. Your request has been received.'
    ]);
}

echo 'OK';

const crypto = require("crypto");
const express = require("express");
const SoftStoreSDK = require("./index");

const app = express();
app.use(express.json({ limit: "16kb" }));

const API_KEY = "RAW_SELLER_API_KEY";
const api = new SoftStoreSDK("https://api.softstore.app/api/v1", API_KEY);

app.post("/softstore-chat-callback", async (req, res) => {
    const payload = req.body;

    if (payload.type !== "message") {
        return res.status(400).json({ error: "Unsupported webhook type" });
    }

    const expected = crypto
        .createHash("sha1")
        .update(API_KEY + payload.id_chat)
        .digest("hex");

    if (expected !== payload.signature) {
        return res.status(403).json({ error: "Invalid signature" });
    }

    const text = String(payload.text || "").trim();

    if (!text || text.length > 1000) {
        return res.status(422).json({ error: "Invalid message text" });
    }

    await api.createApiKey();
    await api.sendChatMessage(payload.id_chat, {
        message: "Hello. Your request has been received."
    });

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

Dialog Flow


Buyer sends message in order chat
↓
SoftStore validates and moderates the buyer message
↓
SoftStore sends POST webhook to seller api_url
↓
Seller validates signature and text
↓
Seller replies via POST /chat/send/{id_chat}
↓
Buyer sees seller response in the order chat
POST Webhook Processing + Product Delivery

Overview

After successful payment SoftStore automatically sends an HTTP webhook request to your configured api_url.

Your server must:

  • Receive webhook notification
  • Validate webhook signature
  • Request full order details
  • Generate digital product/license
  • Send product to customer
Configure webhook URL using: POST /seller/profile

Recommended Flow


Buyer pays product
↓
SoftStore confirms payment
↓
Webhook sent to seller api_url
↓
Seller validates signature
↓
Seller requests GET /orders/info/{id}
↓
Seller generates product/license
↓
Seller sends product via POST /orders/delivery/{token}
↓
Buyer receives product by email

Incoming Webhook Payload


{
  "id_order": "030a3c6f15f2744e58f2e24fd40d3466",
  "id_product": "69f36497dc78f",
  "payment_status": "paid",
  "comment": "@login",
  "signature": "df595764abc185bbf31c5c6334cfade65379feb6",
  "delivery_url": "https://api.softstore.app/api/v1/orders/delivery/TOKEN",
  "token": "d487c01d834dcb296c4f7b5a02e0b0d9df320bb153778d6c20cd26e2c50b40bf"
}

Signature Verification

Verify webhook authenticity before processing:


sha1(
    sha1(api_key) + id_order
)

Get Order Information

Before delivering product you can request full order details:


GET /orders/info/{id_order}

This allows you to identify:

  • Purchased product ID
  • Quantity
  • Customer email
  • Order metadata

{
  "status": "success",
  "data": {
    "id_order": "030a3c6f15f2744e58f2e24fd40d3466",
    "id_product": "69f36497dc78f",
    "count": 3
  }
}

Webhook Implementation Example


<?php

require_once "SellerApi.php";

$apiKey = "YOUR_API_KEY";

/*
|--------------------------------------------------------------------------
| Receive webhook
|--------------------------------------------------------------------------
*/

$payload = json_decode(
    file_get_contents("php://input"),
    true
);

if (!$payload) {
    http_response_code(400);
    exit("Invalid payload");
}

/*
|--------------------------------------------------------------------------
| Verify signature
|--------------------------------------------------------------------------
*/

$expected = sha1(
    sha1($apiKey) . $payload['id_order']
);

if ($expected !== $payload['signature']) {
    http_response_code(403);
    exit("Invalid signature");
}

/*
|--------------------------------------------------------------------------
| Create API client
|--------------------------------------------------------------------------
*/

$api = new SellerApi(
    "https://api.softstore.app/api/v1",
    $apiKey
);

$api->createApiKey();

/*
|--------------------------------------------------------------------------
| Get full order info
|--------------------------------------------------------------------------
*/

$orderInfo = $api->infoOrder(
    $payload['id_order']
);

print_r($orderInfo);

/*
|--------------------------------------------------------------------------
| Deliver product
|--------------------------------------------------------------------------
*/

$response = $api->deliverOrder(
    $payload['token'],
    [
        "text" => "Windows License Key: XXXXX",

        "download" =>
            "https://cdn.yoursite.com/file.zip"

        // or:
        // "download" => false
    ]
);

print_r($response);

http_response_code(200);
echo "Delivered";

const express = require("express");
const crypto = require("crypto");
const axios = require("axios");

const app = express();

app.use(express.json());

const API_KEY = "YOUR_API_KEY";


app.post("/webhook", async (req, res) => {

    try {

        const payload = req.body;

        /*
        --------------------------------------
        Verify signature
        --------------------------------------
        */

        const hashedApiKey = crypto
            .createHash("sha1")
            .update(API_KEY)
            .digest("hex");

        const expected = crypto
            .createHash("sha1")
            .update(
                hashedApiKey + payload.id_order
            )
            .digest("hex");

        if (expected !== payload.signature) {
            return res.status(403).send(
                "Invalid signature"
            );
        }

        /*
        --------------------------------------
        Get JWT token
        --------------------------------------
        */

        const auth = await axios.post(
            "https://api.softstore.app/api/v1/auth/api-key/create",
            {},
            {
                headers: {
                    "X-API-KEY": API_KEY
                }
            }
        );

        const jwt =
            auth.data.data.access_token;

        /*
        --------------------------------------
        Get order details
        --------------------------------------
        */

        const orderInfo = await axios.get(
            `https://api.softstore.app/api/v1/orders/info/${payload.id_order}`,
            {
                headers: {
                    Authorization:
                        `Bearer ${jwt}`
                }
            }
        );

        console.log(orderInfo.data);

        /*
        --------------------------------------
        Deliver product
        --------------------------------------
        */

        const response = await axios.post(
            `https://api.softstore.app/api/v1/orders/delivery/${payload.token}`,
            {
                text:
                    "Windows License Key: XXXXX",

                download:
                    "https://cdn.yoursite.com/file.zip"

                // or:
                // download: false
            },
            {
                headers: {
                    Authorization:
                        `Bearer ${jwt}`
                }
            }
        );

        console.log(response.data);

        return res.status(200).send(
            "Delivered"
        );

    } catch (error) {

        console.error(
            error.response?.data
        );

        return res.status(500).send(
            "Delivery error"
        );
    }

});

app.listen(3000, () => {
    console.log(
        "Webhook server started"
    );
});

Successful Delivery Response


{
  "status": "success",
  "data": {
    "message": "Product delivered successfully",
    "id_order": "030a3c6f15f2744e58f2e24fd40d3466",
    "delivered": true
  }
}

Delivery Errors

HTTP Code Error Description
401 Unauthorized Missing or invalid JWT token
403 Access denied Order belongs to another seller
404 Order not found Invalid delivery token
409 Order already delivered Product already sent
422 Invalid download URL Only HTTPS links allowed

Subscribers API v1

Authenticated sellers can read only their own active subscribers, create scoped discounts and queue Email/Push campaigns. Raw email addresses and push tokens are never returned.

GET    /api/v1/seller/subscribers?page=1&limit=50&date_from=2026-09-01&date_to=2026-09-30
GET    /api/v1/seller/subscriber-statistics?period=month&date=2026-09-18
GET    /api/v1/seller/subscriber-discounts
POST   /api/v1/seller/subscriber-discounts
DELETE /api/v1/seller/subscriber-discounts/{id}
POST   /api/v1/seller/subscriber-campaigns/preview
POST   /api/v1/seller/subscriber-campaigns
GET    /api/v1/seller/subscriber-campaigns/{id}

The public WEB/Android BFF returns only currently active promotions at GET https://app.softstore.app/api/app/v1/sellers/{id}/promotions. Seller API v1 keeps management methods protected by seller authentication.

Discount priority is product > category > all. Discounts do not stack. The selected subscriber percentage is applied after the regular/wholesale price. API v2 and app checkout responses add an optional subscriber_discount object; old clients can ignore it.

Campaigns are asynchronous and idempotent. Delivery rechecks the active subscription and available channel immediately before sending.

SDK Official SDK Libraries

Overview

Official SDK libraries help sellers integrate with SoftStore faster without writing raw API requests manually.

Available SDKs include authentication, product management, order management, webhook processing, and automatic digital product delivery.

Recommended for automated marketplaces, license systems, subscription services, game stores, SaaS sellers, and digital product platforms.

Available SDK Libraries

Generate Additional SDKs

Need another language?

Export our OpenAPI schema and generate your own SDK using:

  • Java
  • Python
  • Go
  • C#
  • Ruby
  • Swift
  • Kotlin
  • TypeScript
Use Swagger Codegen or OpenAPI Generator with our exported schema file.

Quick Start Examples


<?php

require_once "SellerApi.php";

$api = new SellerApi(
    "https://api.softstore.app/api/v1",
    "YOUR_RAW_SELLER_API_KEY"
);

$response = $api->createApiKey(); // alias: authenticate()

if ($response["status"] !== 200) {
    throw new RuntimeException(
        $response["data"]["message"] ?? "API authentication failed"
    );
}

print_r($api->getProducts());

const SellerSDK = require("./seller-sdk");

const api = new SellerSDK(
    "https://api.softstore.app/api/v1",
    "YOUR_RAW_SELLER_API_KEY"
);

async function init() {
    const response = await api.createApiKey(); // alias: authenticate()

    if (response.status !== 200) {
        throw new Error(
            response.data?.message || "API authentication failed"
        );
    }

    console.log(await api.getProducts());
}

init();

Included Features

Feature Supported
JWT Authentication
Raw API key error handling
Create Products
Update Products
Delete Products
Order Management
Payout API
Chat API
Webhook Processing
Automatic Delivery
Image Uploads

JWT API Playground

Test authenticated requests directly from documentation.



      

      

Seller Favorit Products / Избранные товары продавца

Изолированный список основных товаров продавца. Seller ID всегда определяется из Bearer token; добавить или удалить можно только собственный товар.

Ответ товара дополнен необязательным boolean-полем favorit. Старые клиенты могут игнорировать его.

{"product_ids":["id1","id2"]}

HTTP: 200 success/idempotent; 401 auth; 404 own product not found/access denied; 422 invalid ID or bulk payload; 429 rate limit.