API Documentation
Complete REST API documentation.
POST /auth/api-key/create
Generate JWT access token using API key.
curl -X POST https://api.softstore.app/api/v1/auth/api-key/create \
-H "X-API-KEY: YOUR_API_KEY"
Response Schema
| access_token | string |
| expires_in | integer |
Request Overview
This endpoint allows sellers to create a new product in their inventory. The product will be attached to the authenticated seller account.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id_categories | integer | Yes | Existing category identifier |
| name | string | Yes | Product title (3-255 chars) |
| meta_title | string | Yes | SEO meta title |
| meta_description | string | Yes | SEO meta description |
| tags | string | Yes | Comma-separated tags list |
| text_page | string | Yes | Full product description (minimum 10 chars) |
| 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 |
| api_key | string | No | Optional external API integration key |
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
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",
"tags": "windows,key,microsoft",
"text_page": "Official Windows activation key",
"price": 500,
"count": 100,
"uuid": "ext-123456",
"features": "Lifetime activation,Instant delivery,Official key"
}'
$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'
]);
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"
})
}
);
console.log(await response.json());
Success Response
{
"status": "success",
"data": {
"message": "Product created",
"id": "69f8bd078449b"
}
}
Error Responses
{
"status": "error",
"message": "Field 'name' is required"
}
{
"status": "error",
"message": "Product with this UUID already exists"
}
{
"status": "error",
"message": "Invalid category id"
}
Request Overview
This endpoint updates an existing product that belongs to the authenticated seller. Only the product owner can update product data.
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 |
| count | integer | Available stock quantity |
| api_key | string | External API integration key |
| api_url | string | External API URL |
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 |
| tags | string | Product tags |
| text_page | string | Product description |
| uuid | string | External product UUID |
| features | string | Comma-separated product features |
| id_categories | integer | Product category ID |
Restricted Fields
- 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",
"name": "Updated Product Name",
"text_page": "Updated product description",
"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',
'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,
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"
}
Request Overview
This endpoint permanently deletes an existing product from the authenticated seller inventory.
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"
}
Request Overview
Retrieve full information about a specific product that belongs to the authenticated seller account.
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->getProductInfo($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"
}
Request Overview
Returns a paginated list of products that belong to the authenticated seller account.
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 (default: 20) |
| status | string | No | Filter by moderation status |
| category | integer | No | Filter by category ID |
| 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=20" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Accept: application/json"
$response = $api->getProducts([
'page' => 1,
'limit' => 20,
'status' => 'approved'
]);
print_r($response);
const response = await fetch(
'https://api.softstore.app/api/v1/products?page=1&limit=20',
{
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_moderation": "approved"
}
],
"pagination": {
"total": 150,
"page": 1,
"limit": 20
}
}
}
Error Responses
{
"status": "error",
"message": "Unauthorized"
}
{
"status": "error",
"message": "Invalid pagination parameters"
}
Request Overview
This endpoint returns the full list of available product categories that sellers can use when creating or updating products.
id_categories during product creation or update.
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 |
| status | string | Category status |
Business Logic
- Returns only active categories
- Inactive categories may be hidden from sellers
- Category IDs are required for product creation
- 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"
}
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.
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"
}
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 intentionally not exposed in seller API responses or in the seller dashboard.
Headers
Authorization: Bearer YOUR_JWT_TOKEN
Accept: application/json
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 / canceled) |
| 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
- 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"
}
Request Overview
This endpoint returns detailed information about a specific order. Sellers can only access orders that belong to their own account.
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 |
| id_user | string | Registered buyer ID (if available) |
| guest_id | string | Guest buyer identifier |
| buyer_type | string | Buyer type (guest / registered) |
| 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 without buyer email
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",
"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"
}
Overview
This endpoint allows sellers to deliver digital products after receiving a successful payment webhook notification.
{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",
"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
Product keys, credentials, license codes, instructions
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 |
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.
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"
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"
}
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.
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
- 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"
}'
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"
}
Request Overview
This endpoint uploads a product image for an existing product.
Images are uploaded using multipart/form-data.
The image will be linked to the authenticated seller product.
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"
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"
}
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.
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"
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"
}
Request Overview
Create a withdrawal request from seller internal balance. This endpoint requires Google Authenticator OTP verification.
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"
}'
[
'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"
}
Request Overview
Retrieve full payout history for the authenticated seller. Returns withdrawal transactions created from seller balance.
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"
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"
}
Overview
SoftStore automatically sends webhook notifications
to your api_url after successful payment.
POST /seller/profile
Incoming Webhook Payload
{
"id_order": "030a3c6f15f2744e58f2e24fd40d3466",
"id_product": "69f36497dc78f",
"payment_status": "paid",
"signature": "df595764abc185bbf31c5c6334cfade65379feb6",
"delivery_url": "https://api.softstore.app/api/v1/orders/delivery/TOKEN",
"token": "d487c01d834dcb296c4f7b5a02e0b0d9df320bb153778d6c20cd26e2c50b40bf"
}
Signature Verification
Signature formula:
sha1( sha1(api_key) + id_order)
PHP Example
$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";
Node.js Example
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 |
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
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",
"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 |
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.
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
Quick Start Examples
<?php
require_once "SellerApi.php";
$api = new SellerApi(
"https://api.softstore.app/api/v1",
"YOUR_API_KEY"
);
$response = $api->createApiKey();
print_r($response);
const SellerSDK = require("./seller-sdk");
const api = new SellerSDK(
"https://api.softstore.app/api/v1",
"YOUR_API_KEY"
);
async function init() {
const response = await api.createApiKey();
console.log(response);
}
init();
Included Features
| Feature | Supported |
|---|---|
| JWT Authentication | ✔ |
| Create Products | ✔ |
| Update Products | ✔ |
| Delete Products | ✔ |
| Order Management | ✔ |
| Webhook Processing | ✔ |
| Automatic Delivery | ✔ |
| Image Uploads | ✔ |
JWT API Playground
Test authenticated requests directly from documentation.