📚 API Documentation
⚠️ Important Notes:
- Your shop must be active, and valid subscription
- All endpoints return JSON responses
🔍 Overview
The Posts API allows you to manage blog posts, articles, and product reviews, orders, ... for your website.
Each post can have dynamic data fields for flexible content management.
📋 Base URL
https://your-shop-domain.com
🔑 Authentication Methods
⚠️ Important:
- All write operations (POST, PUT, PATCH, DELETE) require JWT authentication
- Read operations (GET) may require authentication depending on shop settings
- JWT tokens expire after 1 hour, refresh tokens expire after 7 days
- Always use HTTPS in production for secure token transmission
- Include JWT token in Authorization header:
Authorization: Bearer YOUR_TOKEN
Shop User Authentication
Use these endpoints to authenticate a Shop User scoped to a specific shop (identified from the request host). The issued tokens include shop_user_id
, shop_id
, and type
set to shop_access
or shop_refresh
.
POST /api/shop_auth/register
Register a new shop user for the current shop and receive JWT tokens.
/api/shop_auth/register
Request Body
- email (string, required)
- password (string, required)
- name (string, optional)
Example Request
curl -X POST "https://your-shop-domain.com/api/shop_auth/register" \
-H "Content-Type: application/json" \
-d '{
"email": "staff@example.com",
"password": "secret",
"name": "Staff"
}'
POST /api/shop_auth/login
Authenticate shop user and receive JWT tokens.
/api/shop_auth/login
Request Body
- email (string, required)
- password (string, required)
Example Request
curl -X POST "https://your-shop-domain.com/api/shop_auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "staff@example.com",
"password": "secret"
}'
Successful Response
{
"success": true,
"message": "Login successful",
"data": {
"user": { "id": 12, "email": "staff@example.com", "name": "Staff" },
"tokens": {
"access_token": "...",
"refresh_token": "...",
"token_type": "Bearer",
"expires_in": 3600
}
}
}
POST /api/shop_auth/refresh
Refresh expired access token using a valid shop refresh token.
/api/shop_auth/refresh
Request Body
- refresh_token (string, required)
Example Request
curl -X POST "https://your-shop-domain.com/api/shop_auth/refresh" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "YOUR_REFRESH_TOKEN"
}'
POST /api/shop_auth/logout
Logout and blacklist current shop access token.
/api/shop_auth/logout
Headers
- Authorization: Bearer YOUR_ACCESS_TOKEN
Example Request
curl -X POST "https://your-shop-domain.com/api/shop_auth/logout" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json"
GET /api/shop_auth/me
Get current authenticated shop user info.
/api/shop_auth/me
Headers
- Authorization: Bearer YOUR_ACCESS_TOKEN
Example Request
curl -X GET "https://your-shop-domain.com/api/shop_auth/me" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json"
🔑 API Key Authentication
For server-to-server integrations, you can use API keys instead of JWT tokens.
Using API Key
curl -X POST "https://your-shop-domain.com/posts" \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"post": {
"title": "API Key Post",
"content": "Created using API key authentication"
}
}'
🔑 Session Authentication
For web applications, you can also use session-based authentication.
Using Session Cookie
curl -X POST "https://your-shop-domain.com/posts" \
-H "Cookie: _session_id=your_session_cookie" \
-H "Content-Type: application/json" \
-d '{
"post": {
"title": "Session Post",
"content": "Created using session authentication"
}
}'
🔑 Using JWT Tokens with Posts API
Complete Workflow with JWT Authentication
# 1. Login to get Shop User JWT tokens
curl -X POST "https://your-shop-domain.com/api/shop_auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "staff@example.com",
"password": "secret"
}'
# Response will contain access_token and refresh_token
# Store these tokens securely
# 2. Create post using JWT token
curl -X POST "https://your-shop-domain.com/posts" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"post": {
"title": "My First Post",
"content": "This is my first post using JWT authentication",
"active": true,
"post_type": "article"
}
}'
# 3. Update post using JWT token
curl -X PUT "https://your-shop-domain.com/posts/1" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"post": {
"title": "Updated Post Title",
"active": false
}
}'
# 4. Refresh token when it expires
curl -X POST "https://your-shop-domain.com/api/shop_auth/refresh" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "YOUR_REFRESH_TOKEN"
}'
# 5. Logout when done
curl -X POST "https://your-shop-domain.com/api/shop_auth/logout" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json"
🚀 API Endpoints
GET /posts
Retrieve a list of posts with optional filtering and pagination.
/posts
Query Parameters
Parameter | Type | Required | Description |
query | string | No | Search term to filter posts |
category_id | integer | No | Filter posts by category ID |
active | boolean | No | Filter by active status |
post_type | string | No | Filter by post type |
page | integer | No | Page number (default: 1) |
per_page | integer | No | Items per page (default: 20, max: 50) |
Example Request
curl -X GET "https://your-shop-domain.com/posts?query=iPhone&category_id=1&page=1&per_page=10" \
-H "Content-Type: application/json"
Success Response
{
"success": true,
"data": {
"posts": [
{
"id": 1,
"title": "iPhone 15 Pro Review",
"content": "Detailed review...",
"active": true,
"post_type": "review",
"category_id": 1,
"body_data": {"product_name": "iPhone 15 Pro", "price": "999"},
"slug": "iphone-15-pro-review",
"created_at": "2023-10-15T10:30:00Z",
"updated_at": "2023-10-15T10:30:00Z"
}
],
"pagination": {
"total_pages": 5,
"current_page": 1,
"per_page": 10,
"total_count": 48
}
}
}
GET /posts/:id
Retrieve a specific post by ID or slug.
/posts/{id_or_slug}
Example Request
curl -X GET "https://your-shop-domain.com/posts/1" \
-H "Content-Type: application/json"
Success Response
{
"success": true,
"data": {
"post": {
"id": 1,
"title": "iPhone 15 Pro Review",
"content": "Detailed review...",
"active": true,
"post_type": "review",
"category_id": 1,
"body_data": {"product_name": "iPhone 15 Pro", "price": "999"},
"slug": "iphone-15-pro-review",
"created_at": "2023-10-15T10:30:00Z",
"updated_at": "2023-10-15T10:30:00Z"
}
}
}
POST /posts
Create a new post.
/posts
Request Body
Field | Type | Required | Description |
post[title] | string | Yes | Post title |
post[content] | text | No | Post content |
post[active] | boolean | No | Active status |
post[post_type] | string | No | Post type |
post[category_id] | integer | No | Category ID |
post[image_link] | string | No | Image URL |
post[body_data] | object | No | Dynamic data fields |
Example Request
curl -X POST "https://your-shop-domain.com/posts" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"post": {
"title": "iPhone 15 Pro Max Review",
"content": "Comprehensive review...",
"active": true,
"post_type": "product_review",
"category_id": 1,
"image_link": "https://example.com/iphone.jpg",
"body_data": {
"brand": "Apple",
"model": "iPhone 15 Pro Max",
"price_usd": "1199",
"rating": "4.8",
"colors": "Natural Titanium, Blue Titanium"
}
}
}'
Success Response (201 Created)
{
"success": true,
"message": "Post created successfully",
"data": {
"post": {
"id": 2,
"title": "iPhone 15 Pro Max Review",
"slug": "iphone-15-pro-max-review",
"created_at": "2023-10-15T11:00:00Z",
"updated_at": "2023-10-15T11:00:00Z"
}
}
}
PUT/PATCH /posts/:id
Update an existing post.
/posts/{id_or_slug}
Example Request
curl -X PUT "https://your-shop-domain.com/posts/1" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"post": {
"title": "Updated iPhone 15 Pro Review",
"active": true,
"body_data": {
"price": "899",
"discount": "10%"
}
}
}'
Success Response
{
"success": true,
"message": "Post updated successfully",
"data": {
"post": {
"id": 1,
"title": "Updated iPhone 15 Pro Review",
"updated_at": "2023-10-15T12:00:00Z"
}
}
}
DELETE /posts/:id
Delete a post.
/posts/{id_or_slug}
Example Request
curl -X DELETE "https://your-shop-domain.com/posts/1" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json"
Success Response
{
"success": true,
"message": "Post deleted successfully"
}
GET /posts/search
Advanced search functionality for posts.
/posts/search
Query Parameters
Parameter | Type | Required | Description |
q | string | No | Search query |
category_id | integer | No | Filter by category |
active | boolean | No | Filter by status |
post_type | string | No | Filter by type |
body_data_key | string | No | Search by body_data key |
body_data_value | string | No | Search by body_data value |
page | integer | No | Page number |
per_page | integer | No | Items per page |
Example Request
curl -X GET "https://your-shop-domain.com/posts/search?body_data_key=brand&body_data_value=Apple&page=1&per_page=20" \
-H "Content-Type: application/json"
GET /posts/:id/body_data
Retrieve only the dynamic data of a specific post.
/posts/{id_or_slug}/body_data
Example Request
curl -X GET "https://your-shop-domain.com/posts/1/body_data" \
-H "Content-Type: application/json"
Success Response
{
"success": true,
"data": {
"body_data": {
"brand": "Apple",
"model": "iPhone 15 Pro Max",
"price_usd": "1199",
"rating": "4.8"
},
"dynamic_variables_count": 4,
"available_keys": ["brand", "model", "price_usd", "rating"]
}
}
PATCH /posts/:id/update_body_data
Update only the dynamic data of a specific post.
/posts/{id_or_slug}/update_body_data
Example Request
curl -X PATCH "https://your-shop-domain.com/posts/1/update_body_data" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"post": {
"body_data": {
"price": "899",
"discount": "25%",
"sale_end_date": "2023-12-31",
"stock_quantity": "50"
}
}
}'
Success Response
{
"success": true,
"message": "Body data updated successfully",
"data": {
"body_data": {
"price": "899",
"discount": "25%",
"sale_end_date": "2023-12-31",
"stock_quantity": "50"
},
"dynamic_variables_count": 4
}
}
🔧 Body Data Validation Rules
⚠️ Important Validation Rules for body_data:
- Maximum keys: 50 keys per post
- Key format: Only letters, numbers, underscore (_), and hyphen (-)
- Key length: Maximum 100 characters
- Value length: Maximum 1,000 characters for strings
- Total size: Maximum 100KB for entire body_data object
- Reserved keys: Cannot use: title, content, slug, post_type, category_id
- Forbidden content: No script tags, javascript: protocol, or data: URIs
- Value types: Only strings, numbers, booleans, and null values
🚨 Error Responses
Common Error Codes
Status Code | Error Type | Description |
400 | Bad Request | Invalid request parameters |
403 | Forbidden | Shop validation failed |
404 | Not Found | Post not found |
422 | Unprocessable Entity | Validation errors |
500 | Internal Server Error | Server error |
Example Error Responses
Shop Validation Error (403):
{
"success": false,
"error": "Shop is not active"
}
Validation Error (422):
{
"success": false,
"error": "Failed to create post",
"validation_errors": [
"Title can't be blank",
"Body data key 'invalid@key' contains invalid characters"
]
}
📝 Complete Workflow Example
Create, Update, and Delete a Post
# 1. Create a new post
curl -X POST "https://your-shop-domain.com/posts" \
-H "Content-Type: application/json" \
-d '{
"post": {
"title": "Test Product Review",
"content": "This is a test review",
"active": true,
"post_type": "review",
"category_id": 1,
"body_data": {
"product_name": "Test Product",
"price": "99.99",
"rating": "4.5"
}
}
}'
# 2. Get the created post
curl -X GET "https://your-shop-domain.com/posts/1" \
-H "Content-Type: application/json"
# 3. Update the post
curl -X PUT "https://your-shop-domain.com/posts/1" \
-H "Content-Type: application/json" \
-d '{
"post": {
"title": "Updated Test Product Review",
"body_data": {
"price": "89.99",
"discount": "10%"
}
}
}'
# 4. Search for the post
curl -X GET "https://your-shop-domain.com/posts/search?q=Test&active=true" \
-H "Content-Type: application/json"
# 5. Delete the post
curl -X DELETE "https://your-shop-domain.com/posts/1" \
-H "Content-Type: application/json"
🔗 Additional Resources
- Rate Limiting: No specific rate limits, but be reasonable
- Pagination: Always use pagination for large datasets
- Search: Use the search endpoint for complex queries
- Body Data: Use for flexible, dynamic content storage
- Slugs: Automatically generated from titles
⚠️ Production Considerations
- Always include proper error handling
- Use HTTPS in production environments
- Implement proper caching strategies
- Monitor API usage and performance
- Keep body_data size reasonable
🌐 Landing Pages API
The Landing Pages API allows you to manage static and dynamic landing pages for your shop.
GET /lp
List (Search) Landing Pages
/lp.json
Query Parameters
Parameter | Type | Required | Description |
query | string | No | Search query |
page | integer | No | Page number for pagination (default: 1) |
per_page | integer | No | Number of items per page (default: 20) |
category_id | integer | No | Filter by category ID |
ids | string | No | Comma-separated list of specific page IDs (e.g., "1,2,3,4") |
Example Request
curl -X GET "https://your-shop-domain.com/lp.json?query=marketing&page=1&per_page=10&category_id=5" \
-H "Content-Type: application/json"
Success Response
{
"data": [
{
"id": 1,
"name": "Marketing Landing Page",
"slug": "marketing-landing-page",
"page_type": "static",
"keyword": "marketing",
"intro": "Professional marketing landing page",
"category_id": 5,
"active": true,
"copy_from_id": null,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"pagination": {
"total_pages": 10,
"current_page": 1,
"per_page": 20,
"total_count": 200
}
}
Note: This endpoint uses Searchkick for full-text search. The query
parameter supports advanced search syntax.
GET /lp/:id
Detail Landing Page
/lp/{id}.json
Parameters
Parameter | Type | Required | Description |
id | integer | Yes | Landing page ID or slug (friendly find) |
Example Request
curl -X GET "https://your-shop-domain.com/lp/1.json" \
-H "Content-Type: application/json"
Success Response
{
"data": {
"id": 1,
"name": "Marketing Landing Page",
"slug": "marketing-landing-page",
"page_type": "static",
"keyword": "marketing",
"intro": "Professional marketing landing page with call-to-action",
"content": "<html><body><h1>Welcome to our marketing page</h1>...</body></html>",
"category_id": 5,
"active": true,
"copy_from_id": null,
"body_data": {
"custom_field_1": "value1",
"custom_field_2": "value2"
},
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
Note: The body_data
field contains dynamic variables specific to the landing page. This field is excluded from the list endpoint for performance.
💬 Feedback API
The Feedback API allows you to submit feedback and reviews for your shop.
POST /feedbacks
Create Feedback
/feedbacks.json
Parameters
Parameter | Type | Required | Description |
feedback[name] | string | Yes | Name of the person providing feedback |
feedback[email] | string | Yes | Email address of the person |
feedback[content] | string | Yes | Feedback message content. Can be plain text or JSON object for structured data |
Example Request
curl -X POST "https://your-shop-domain.com/feedbacks.json" \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: [your_csrf_token]" \
-d '{
"feedback": {
"name": "John Doe",
"email": "john@example.com",
"content": "Great website! Very user-friendly interface."
}
}'
Example Request with Structured JSON Content
curl -X POST "https://your-shop-domain.com/feedbacks.json" \
-H "Content-Type: application/json" \
-H "X-CSRF-Token: [your_csrf_token]" \
-d '{
"feedback": {
"name": "John Doe",
"email": "john@example.com",
"content": "{\"rating\": \"5\", \"category\": \"UI/UX\", \"suggestion\": \"Add dark mode\"}"
}
}'
Success Response
{
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"content": "Great website! Very user-friendly interface.",
"shop_id": 5,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
Success Response (with JSON content)
{
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"content": "{\"rating\": \"5\", \"category\": \"UI/UX\", \"suggestion\": \"Add dark mode\"}",
"shop_id": 5,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
Rate Limit Exceeded Response
Content Field: The content
field accepts both plain text and JSON strings. When JSON is provided, it will be parsed and displayed as a structured table in the admin interface.
Stored: See your feedbacks/subscribe/post ... in admin dashboard.
🚨 Error Responses
Common Error Codes
Status Code | Description | Example |
404 | Landing page not found | {"error": "Landing page not found"} |
422 | Validation error | {"errors": {"title": ["can't be blank"]}} |
422 | Rate limit exceeded | {"msg": "error req"} |
500 | Internal server error | {"error": "Internal server error"} |