API v2 reference — Admin (Core)

🌐 Language: 🇻🇳 Tiếng Việt · 🇬🇧 English (current) · 🇯🇵 日本語

API v2 reference — Admin (Core)

This page is generated from openapi.json by tools/openapi-to-markdown.php — do not edit it by hand.

Every endpoint under api/v2/core — data for administrators and back-office systems (ERP, CRM, warehouse) — with the admin permission it needs, its parameters, an example call and what it returns.

New to the API? Start with Quick start. Rules shared by every endpoint (response format, paging, fields, include, 304) are in Conventions; each error code is explained in Troubleshooting.

Contents

  • Admin · Sign-in & sessions — Administrator sign-in, token refresh, two-step sign-in, own account and signed-in devices.
  • Admin · Catalog — Products, categories, brands and suppliers as the admin screens show them; product changes.
  • Admin · Stock — Stock changes for one product or many at once (warehouse / ERP sync).
  • Admin · Content — Banners and content pages as the admin screens show them.
  • Admin · Customers — Customer accounts and locking or unlocking an account.
  • Admin · Orders — Orders, their status, delivery details and notes.
  • Admin · Sync — Event log for ERP / sync tools: every change of orders, stock, products and customers, read by cursor.
  • Data objects

Admin · Sign-in & sessions

Administrator sign-in, token refresh, two-step sign-in, own account and signed-in devices.

Signed-in admin profile — GET /api/v2/core/info

Returns the profile and role slugs of the admin who owns the token. Any active admin token may call it; no screen permission is needed.

Sign-in Admin token (Bearer).
Permission None beyond a valid admin token.
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since core 3.3.0

Parameters

Name In Type Meaning
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/info" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: AdminInfo

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "username": "admin",
        "name": "Administrator",
        "email": "admin@example.com",
        "avatar": null,
        "status": 1,
        "roles": [
            "administrator"
        ],
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00"
    }
}

Admin sign-in — POST /api/v2/core/login

Signs an active admin in with username and password and returns a bearer token. With with_refresh=true the answer adds a refresh token and the access token lives a short time. When a plugin requires a second step (MFA), the answer is 401 challenge_required with a ticket to finish on login/challenge. Failed attempts are limited per account and IP.

Sign-in None — this call signs in.
Permission None beyond a valid admin token.
Since core 3.3.0

Request body: AdminLoginV2

Example request

curl -X POST "https://shop.example.com/api/v2/core/login" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"username":"","password":"","remember_me":false,"with_refresh":false,"device_name":""}'

Response 200 — data: SessionToken

{
    "data": {
        "access_token": "12|XyZ...plain-token",
        "token_type": "Bearer",
        "scopes": [
            "user"
        ],
        "expires_at": "2026-11-03 09:00:00",
        "expires_in": 3600,
        "session_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "refresh_token": "a1b2c3...64chars",
        "refresh_expires_at": "2026-12-03 08:00:00",
        "cart_merge": {
            "merged": 2,
            "dropped": 0
        }
    }
}

Errors: validation_failed · unauthenticated · too_many_attempts · challenge_required · challenge_invalid

Admin sign-out — POST /api/v2/core/logout

Signs the current session out: its access token stops working and its refresh token can no longer be used. Any active admin token may call it.

Sign-in Admin token (Bearer).
Permission None beyond a valid admin token.
Since core 3.3.0

Example request

curl -X POST "https://shop.example.com/api/v2/core/logout" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: AdminLogoutResult

{
    "data": {
        "revoked": true
    }
}

Finish admin MFA sign-in — POST /api/v2/core/login/challenge

Sends the ticket from a challenge_required answer together with the plugin's own fields (e.g. a one-time code). On success it answers like login. A wrong answer counts against the login limit; a ticket lives 5 minutes and allows 5 wrong answers.

Sign-in None — this call signs in.
Permission None beyond a valid admin token.
Since core 3.5.1

Request body: LoginChallengeAnswer

Example request

curl -X POST "https://shop.example.com/api/v2/core/login/challenge" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"ticket":""}'

Response 200 — data: SessionToken

{
    "data": {
        "access_token": "12|XyZ...plain-token",
        "token_type": "Bearer",
        "scopes": [
            "user"
        ],
        "expires_at": "2026-11-03 09:00:00",
        "expires_in": 3600,
        "session_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "refresh_token": "a1b2c3...64chars",
        "refresh_expires_at": "2026-12-03 08:00:00",
        "cart_merge": {
            "merged": 2,
            "dropped": 0
        }
    }
}

Errors: validation_failed · challenge_invalid · too_many_attempts

Refresh admin access token — POST /api/v2/core/refresh

Exchanges a refresh token for a new access token and a new refresh token; each refresh token works once. Using a spent token again signs the whole session out (refresh_token_reused), except within 10 seconds of its use (refresh_in_progress). Answers 404 when the site has not run gp247:update yet.

Sign-in None — this call signs in.
Permission None beyond a valid admin token.
Since core 3.5.1

Request body: RefreshRequest

Example request

curl -X POST "https://shop.example.com/api/v2/core/refresh" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"refresh_token":""}'

Response 200 — data: SessionToken

{
    "data": {
        "access_token": "12|XyZ...plain-token",
        "token_type": "Bearer",
        "scopes": [
            "user"
        ],
        "expires_at": "2026-11-03 09:00:00",
        "expires_in": 3600,
        "session_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "refresh_token": "a1b2c3...64chars",
        "refresh_expires_at": "2026-12-03 08:00:00",
        "cart_merge": {
            "merged": 2,
            "dropped": 0
        }
    }
}

Errors: validation_failed · not_found · refresh_token_invalid · refresh_token_reused · refresh_in_progress · unauthenticated

List admin sessions — GET /api/v2/core/sessions

Returns the live API sessions (devices) of the signed-in admin, newest first, with the current one flagged. No token material is returned. Not paginated; an empty array before the site runs gp247:update.

Sign-in Admin token (Bearer).
Permission None beyond a valid admin token.
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since core 3.5.1

Parameters

Name In Type Meaning
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/sessions" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Session

{
    "data": [
        {
            "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "name": "Pixel 8",
            "ip": "203.0.113.5",
            "created_at": "2026-10-31T08:00:00+07:00",
            "last_used_at": "2026-10-31T08:00:00+07:00",
            "refreshable": true,
            "refresh_expires_at": "2026-11-30T08:00:00+07:00",
            "current": true
        }
    ]
}

Sign one admin session out — DELETE /api/v2/core/sessions/{id}

Signs one of the admin's own sessions out (its access and refresh token). Another owner's session id answers 404.

Sign-in Admin token (Bearer).
Permission None beyond a valid admin token.
Since core 3.5.1

Example request

curl -X DELETE "https://shop.example.com/api/v2/core/sessions/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: AdminSessionsDeleteResult

{
    "data": {
        "revoked": true
    }
}

Errors: not_found

Admin · Catalog

Products, categories, brands and suppliers as the admin screens show them; product changes.

Get one brand (admin) — GET /api/v2/core/brand/detail/{id}

Returns one brand of the admin's store with the admin-only fields. A record of another store answers 404. Accepts fields[brand]=a,b.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Brands (gp247_admin/brand).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/brand/detail/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: Brand

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "name": "Acme",
        "alias": "acme",
        "image": "/data/brand/acme.png",
        "url": "https://acme.example.com",
        "sort": 0,
        "status": 1,
        "store_id": "1",
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00"
    }
}

Errors: not_found · validation_failed

List brands (admin) — GET /api/v2/core/brand/list

Returns the brands of the admin's store, page by page. Requires an admin token allowed to open the matching admin screen. Filter by status, sort by sort or name, search by name. Accepts fields[brand]=a,b to return only some fields. Supports updated_since=<ISO 8601> sync mode: oldest change first, paged with page[after] (meta then has per_page, next_after, has_more, sync_until; links only next).

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Brands (gp247_admin/brand).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
page[number] query integer Page to read, from 1.
page[size] query integer Rows per page (default 20, max 100).
updated_since query string (date-time) Sync mode (since core 3.7.0): ISO-8601 date-time, e.g. 2026-10-31T08:00:00+07:00 (date only or no offset = site timezone). Returns rows with updated_at >= updated_since, oldest change first (updated_at, then id). Cannot be combined with sort or page[number] (422)
page[after] query string Sync mode only: cursor from meta.next_after of the previous page; any other value = 422
filter query object filter[<name>]=value — allowed names per resource, see api-introduction section 8; unknown name = 422
sort query string <name> ascending, -<name> descending; unknown name = 422
q query string Search term
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/brand/list" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Brand — with meta (paging) and links.

{
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 135,
        "last_page": 7,
        "next_after": "eyJ0IjoiMjAyNi0xMC0zMSAwODowMDowMCIsImsiOiI5ZjBjIn0",
        "has_more": true,
        "sync_until": "2026-10-31T08:00:00+07:00"
    },
    "links": {
        "first": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=1&page%5Bsize%5D=20",
        "last": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=7&page%5Bsize%5D=20",
        "prev": null,
        "next": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=2&page%5Bsize%5D=20"
    },
    "data": [
        {
            "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "name": "Acme",
            "alias": "acme",
            "image": "/data/brand/acme.png",
            "url": "https://acme.example.com",
            "sort": 0,
            "status": 1,
            "store_id": "1",
            "created_at": "2026-10-31T08:00:00+07:00",
            "updated_at": "2026-10-31T08:00:00+07:00"
        }
    ]
}

Errors: validation_failed

Get one category (admin) — GET /api/v2/core/category/detail/{id}

Returns one category of the admin's store with the admin-only fields. A record of another store answers 404. Accepts fields[category]=a,b.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Categories (gp247_admin/category).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/category/detail/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: Category

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "alias": "t-shirts",
        "name": "T-shirts",
        "keyword": "t-shirt",
        "description": "All our T-shirts.",
        "image": "/data/category/tshirts.jpg",
        "parent": null,
        "top": 1,
        "sort": 0,
        "status": 1,
        "store_id": "1",
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00"
    }
}

Errors: not_found · validation_failed

List categories (admin) — GET /api/v2/core/category/list

Returns the categories of the admin's store, page by page. Requires an admin token allowed to open the matching admin screen. Text fields in the language given by ?lang=. Filter by parent or status, sort by sort or created_at, search by name. Accepts fields[category]=a,b to return only some fields. Supports updated_since=<ISO 8601> sync mode: oldest change first, paged with page[after] (meta then has per_page, next_after, has_more, sync_until; links only next).

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Categories (gp247_admin/category).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
page[number] query integer Page to read, from 1.
page[size] query integer Rows per page (default 20, max 100).
updated_since query string (date-time) Sync mode (since core 3.7.0): ISO-8601 date-time, e.g. 2026-10-31T08:00:00+07:00 (date only or no offset = site timezone). Returns rows with updated_at >= updated_since, oldest change first (updated_at, then id). Cannot be combined with sort or page[number] (422)
page[after] query string Sync mode only: cursor from meta.next_after of the previous page; any other value = 422
filter query object filter[<name>]=value — allowed names per resource, see api-introduction section 8; unknown name = 422
sort query string <name> ascending, -<name> descending; unknown name = 422
q query string Search term
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/category/list" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Category — with meta (paging) and links.

{
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 135,
        "last_page": 7,
        "next_after": "eyJ0IjoiMjAyNi0xMC0zMSAwODowMDowMCIsImsiOiI5ZjBjIn0",
        "has_more": true,
        "sync_until": "2026-10-31T08:00:00+07:00"
    },
    "links": {
        "first": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=1&page%5Bsize%5D=20",
        "last": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=7&page%5Bsize%5D=20",
        "prev": null,
        "next": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=2&page%5Bsize%5D=20"
    },
    "data": [
        {
            "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "alias": "t-shirts",
            "name": "T-shirts",
            "keyword": "t-shirt",
            "description": "All our T-shirts.",
            "image": "/data/category/tshirts.jpg",
            "parent": null,
            "top": 1,
            "sort": 0,
            "status": 1,
            "store_id": "1",
            "created_at": "2026-10-31T08:00:00+07:00",
            "updated_at": "2026-10-31T08:00:00+07:00"
        }
    ]
}

Errors: validation_failed

Get one product (admin) — GET /api/v2/core/product/detail/{id}

Returns one product of the admin's store with the admin-only fields. A record of another store answers 404. Accepts fields[product]=a,b and include=images,brand,categories.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Products (gp247_admin/product).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.
include query string Comma-separated related records to embed (one level, at most 3): images, brand, categories. Anything else = 422. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/product/detail/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: Product

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "sku": "TSHIRT-RED-M",
        "alias": "red-t-shirt",
        "name": "Red T-shirt",
        "keyword": "t-shirt, red",
        "description": "Soft cotton T-shirt.",
        "content": "<p>Soft cotton T-shirt.</p>",
        "image": "/data/product/tshirt.jpg",
        "images": [
            "/data/product/tshirt-2.jpg"
        ],
        "price": 200000,
        "price_final": 180000,
        "tax_id": "auto",
        "kind": 0,
        "product_type": "physical",
        "brand_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "category_ids": [
            "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f"
        ],
        "minimum": 1,
        "weight": 0.3,
        "weight_class": "kg",
        "length": 30,
        "width": 20,
        "height": 2,
        "length_class": "cm",
        "date_available": "2026-11-01",
        "store_id": "1",
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00",
        "image_sizes": {
            "original": "https://shop.example.com/data/product/tshirt.jpg",
            "thumb": "https://shop.example.com/data/product/thumb/tshirt.jpg"
        },
        "stock_status": "in_stock",
        "attributes": [
            {
                "group_id": "1",
                "name": "Color",
                "required": true,
                "options": [
                    {
                        "value": "Red",
                        "add_price": 0
                    }
                ]
            }
        ],
        "cost": 120000,
        "stock": 15,
        "sold": 42,
        "status": 1,
        "approve": 1,
        "supplier_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "view": 310
    }
}

Errors: not_found · validation_failed

Update product price, cost, status — PATCH /api/v2/core/product/{id}

Changes the selling price, cost price and/or status (0 or 1) of a product of the admin's store. Any other field, or a price field the store turned off in product settings, is refused with 422. Answers the full admin product. Idempotency-Key optional.

Sign-in Admin token (Bearer).
Permission Write access to the admin screen Products (gp247_admin/product).
Since shop 3.6.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
Idempotency-Key header string Optional; 8-255 printable characters (e.g. a UUID). A retry with the same key and body answers the first result

Request body: AdminProductUpdateRequest

Example request

curl -X PATCH "https://shop.example.com/api/v2/core/product/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"price":0,"cost":0,"status":0}'

Response 200 — data: Product

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "sku": "TSHIRT-RED-M",
        "alias": "red-t-shirt",
        "name": "Red T-shirt",
        "keyword": "t-shirt, red",
        "description": "Soft cotton T-shirt.",
        "content": "<p>Soft cotton T-shirt.</p>",
        "image": "/data/product/tshirt.jpg",
        "images": [
            "/data/product/tshirt-2.jpg"
        ],
        "price": 200000,
        "price_final": 180000,
        "tax_id": "auto",
        "kind": 0,
        "product_type": "physical",
        "brand_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "category_ids": [
            "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f"
        ],
        "minimum": 1,
        "weight": 0.3,
        "weight_class": "kg",
        "length": 30,
        "width": 20,
        "height": 2,
        "length_class": "cm",
        "date_available": "2026-11-01",
        "store_id": "1",
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00",
        "image_sizes": {
            "original": "https://shop.example.com/data/product/tshirt.jpg",
            "thumb": "https://shop.example.com/data/product/thumb/tshirt.jpg"
        },
        "stock_status": "in_stock",
        "attributes": [
            {
                "group_id": "1",
                "name": "Color",
                "required": true,
                "options": [
                    {
                        "value": "Red",
                        "add_price": 0
                    }
                ]
            }
        ],
        "cost": 120000,
        "stock": 15,
        "sold": 42,
        "status": 1,
        "approve": 1,
        "supplier_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "view": 310
    }
}

Errors: not_found · validation_failed · forbidden · idempotency_key_required · idempotency_key_reused · idempotency_in_progress · idempotency_unavailable

List products (admin) — GET /api/v2/core/product/list

Returns the products of the admin's store, page by page. Requires an admin token allowed to open the matching admin screen. Includes inventory and moderation fields (cost, stock, sold, status, approve, supplier_id, view) and every product whatever its status. Filters: category_id, brand_id, kind, product_type, price_min, price_max, status, approve, supplier_id; sort by price, created_at, sort or sku; search by SKU or name; include=images,brand,categories. Accepts fields[product]=a,b to return only some fields. Supports updated_since=<ISO 8601> sync mode: oldest change first, paged with page[after] (meta then has per_page, next_after, has_more, sync_until; links only next).

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Products (gp247_admin/product).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
page[number] query integer Page to read, from 1.
page[size] query integer Rows per page (default 20, max 100).
updated_since query string (date-time) Sync mode (since core 3.7.0): ISO-8601 date-time, e.g. 2026-10-31T08:00:00+07:00 (date only or no offset = site timezone). Returns rows with updated_at >= updated_since, oldest change first (updated_at, then id). Cannot be combined with sort or page[number] (422)
page[after] query string Sync mode only: cursor from meta.next_after of the previous page; any other value = 422
filter query object filter[<name>]=value — allowed names per resource, see api-introduction section 8; unknown name = 422
sort query string <name> ascending, -<name> descending; unknown name = 422
q query string Search term
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.
include query string Comma-separated related records to embed (one level, at most 3): images, brand, categories. Anything else = 422. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/product/list" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Product — with meta (paging) and links.

{
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 135,
        "last_page": 7,
        "next_after": "eyJ0IjoiMjAyNi0xMC0zMSAwODowMDowMCIsImsiOiI5ZjBjIn0",
        "has_more": true,
        "sync_until": "2026-10-31T08:00:00+07:00"
    },
    "links": {
        "first": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=1&page%5Bsize%5D=20",
        "last": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=7&page%5Bsize%5D=20",
        "prev": null,
        "next": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=2&page%5Bsize%5D=20"
    },
    "data": [
        {
            "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "sku": "TSHIRT-RED-M",
            "alias": "red-t-shirt",
            "name": "Red T-shirt",
            "keyword": "t-shirt, red",
            "description": "Soft cotton T-shirt.",
            "content": "<p>Soft cotton T-shirt.</p>",
            "image": "/data/product/tshirt.jpg",
            "images": [
                "/data/product/tshirt-2.jpg"
            ],
            "price": 200000,
            "price_final": 180000,
            "tax_id": "auto",
            "kind": 0,
            "product_type": "physical",
            "brand_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "category_ids": [
                "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f"
            ],
            "minimum": 1,
            "weight": 0.3,
            "weight_class": "kg",
            "length": 30,
            "width": 20,
            "height": 2,
            "length_class": "cm",
            "date_available": "2026-11-01",
            "store_id": "1",
            "created_at": "2026-10-31T08:00:00+07:00",
            "updated_at": "2026-10-31T08:00:00+07:00",
            "image_sizes": {
                "original": "https://shop.example.com/data/product/tshirt.jpg",
                "thumb": "https://shop.example.com/data/product/thumb/tshirt.jpg"
            },
            "stock_status": "in_stock",
            "attributes": [
                {
                    "group_id": "1",
                    "name": "Color",
                    "required": true,
                    "options": [
                        {
                            "value": "Red",
                            "add_price": 0
                        }
                    ]
                }
            ],
            "cost": 120000,
            "stock": 15,
            "sold": 42,
            "status": 1,
            "approve": 1,
            "supplier_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "view": 310
        }
    ]
}

Errors: validation_failed

Get one supplier (admin) — GET /api/v2/core/supplier/detail/{id}

Returns one supplier of the admin's store with the admin-only fields. A record of another store answers 404. Accepts fields[supplier]=a,b.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Suppliers (gp247_admin/supplier).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/supplier/detail/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: Supplier

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "name": "Acme Supply",
        "alias": "acme-supply",
        "email": "sales@acme.example.com",
        "phone": "+84 28 1234 5678",
        "image": null,
        "address": "1 Main St, Ho Chi Minh City",
        "url": null,
        "sort": 0,
        "status": 1,
        "store_id": "1",
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00"
    }
}

Errors: not_found · validation_failed

List suppliers (admin) — GET /api/v2/core/supplier/list

Returns the suppliers of the admin's store, page by page. Requires an admin token allowed to open the matching admin screen. Filter by status, sort by sort or name, search by name or e-mail. Accepts fields[supplier]=a,b to return only some fields. Supports updated_since=<ISO 8601> sync mode: oldest change first, paged with page[after] (meta then has per_page, next_after, has_more, sync_until; links only next).

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Suppliers (gp247_admin/supplier).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
page[number] query integer Page to read, from 1.
page[size] query integer Rows per page (default 20, max 100).
updated_since query string (date-time) Sync mode (since core 3.7.0): ISO-8601 date-time, e.g. 2026-10-31T08:00:00+07:00 (date only or no offset = site timezone). Returns rows with updated_at >= updated_since, oldest change first (updated_at, then id). Cannot be combined with sort or page[number] (422)
page[after] query string Sync mode only: cursor from meta.next_after of the previous page; any other value = 422
filter query object filter[<name>]=value — allowed names per resource, see api-introduction section 8; unknown name = 422
sort query string <name> ascending, -<name> descending; unknown name = 422
q query string Search term
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/supplier/list" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Supplier — with meta (paging) and links.

{
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 135,
        "last_page": 7,
        "next_after": "eyJ0IjoiMjAyNi0xMC0zMSAwODowMDowMCIsImsiOiI5ZjBjIn0",
        "has_more": true,
        "sync_until": "2026-10-31T08:00:00+07:00"
    },
    "links": {
        "first": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=1&page%5Bsize%5D=20",
        "last": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=7&page%5Bsize%5D=20",
        "prev": null,
        "next": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=2&page%5Bsize%5D=20"
    },
    "data": [
        {
            "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "name": "Acme Supply",
            "alias": "acme-supply",
            "email": "sales@acme.example.com",
            "phone": "+84 28 1234 5678",
            "image": null,
            "address": "1 Main St, Ho Chi Minh City",
            "url": null,
            "sort": 0,
            "status": 1,
            "store_id": "1",
            "created_at": "2026-10-31T08:00:00+07:00",
            "updated_at": "2026-10-31T08:00:00+07:00"
        }
    ]
}

Errors: validation_failed

Admin · Stock

Stock changes for one product or many at once (warehouse / ERP sync).

Move or set product stock — POST /api/v2/core/product/{id}/stock

Receives or issues goods with delta (positive or negative), or overwrites the stock after a count with set (administrators only). Stock never goes below zero and the sold counter is untouched; build products are refused. An Idempotency-Key header is required so a retry never moves stock twice.

Sign-in Admin token (Bearer).
Permission Write access to the admin screen Products (gp247_admin/product).
Since shop 3.6.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
Idempotency-Key (required) header string Required; 8-255 printable characters (e.g. a UUID). A retry with the same key and body moves the stock once and answers the first result (header Idempotent-Replayed: true)

Request body: AdminProductStockRequest

Example request

curl -X POST "https://shop.example.com/api/v2/core/product/123/stock" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"delta":0,"set":0}'

Response 200 — data: AdminProductStockResult

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "sku": "TSHIRT-RED-M",
        "stock": 15
    }
}

Errors: idempotency_key_required · idempotency_key_reused · idempotency_in_progress · idempotency_unavailable · validation_failed · not_found · forbidden · stock_managed_by_components · stock_would_be_negative

Move stock of many products — POST /api/v2/core/stock/batch

Applies 1 to 100 stock lines, each naming a product by id or SKU with delta or set. Each line gets its own result and a bad line never stops the others; the answer is 200 even when some lines fail. Idempotency-Key required.

Sign-in Admin token (Bearer).
Permission Write access to the admin screen Products (gp247_admin/product).
Since shop 3.6.0

Parameters

Name In Type Meaning
Idempotency-Key (required) header string Required; 8-255 printable characters (e.g. a UUID). A retry with the same key and body moves the stock once and answers the first result (header Idempotent-Replayed: true)

Request body: AdminStockBatchRequest

Example request

curl -X POST "https://shop.example.com/api/v2/core/stock/batch" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"items":[[]]}'

Response 200 — data: AdminStockBatchResult

{
    "data": {
        "results": [],
        "ok": 9,
        "failed": 1
    }
}

Errors: idempotency_key_required · idempotency_key_reused · idempotency_in_progress · idempotency_unavailable · validation_failed · forbidden

Admin · Content

Banners and content pages as the admin screens show them.

Get one banner (admin) — GET /api/v2/core/banner/detail/{id}

Returns one banner of the admin's store, including the click counter. Requires an admin token allowed to open the Banners screen; a banner of another store answers 404.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Banners (gp247_admin/banner).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since front 3.3.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/banner/detail/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: Banner

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "name": "Autumn sale",
        "image": "/data/banner/autumn.jpg",
        "url": "https://shop.example.com/sale",
        "target": "_self",
        "html": null,
        "type": "banner",
        "sort": 0,
        "status": 1,
        "store_id": "1",
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00",
        "click": 57
    }
}

Errors: not_found

List banners (admin) — GET /api/v2/core/banner/list

Returns the banners of the admin's store, page by page, including the click counter. Requires an admin token allowed to open the Banners screen. Filter by type, sort by sort or created_at, search by name.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Banners (gp247_admin/banner).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since front 3.3.0

Parameters

Name In Type Meaning
page[number] query integer Page to read, from 1.
page[size] query integer Rows per page (default 20, max 100).
updated_since query string (date-time) Sync mode (since core 3.7.0): ISO-8601 date-time, e.g. 2026-10-31T08:00:00+07:00 (date only or no offset = site timezone). Returns rows with updated_at >= updated_since, oldest change first (updated_at, then id). Cannot be combined with sort or page[number] (422)
page[after] query string Sync mode only: cursor from meta.next_after of the previous page; any other value = 422
filter query object filter[<name>]=value — allowed names per resource, see api-introduction section 8; unknown name = 422
sort query string <name> ascending, -<name> descending; unknown name = 422
q query string Search term
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/banner/list" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Banner — with meta (paging) and links.

{
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 135,
        "last_page": 7,
        "next_after": "eyJ0IjoiMjAyNi0xMC0zMSAwODowMDowMCIsImsiOiI5ZjBjIn0",
        "has_more": true,
        "sync_until": "2026-10-31T08:00:00+07:00"
    },
    "links": {
        "first": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=1&page%5Bsize%5D=20",
        "last": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=7&page%5Bsize%5D=20",
        "prev": null,
        "next": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=2&page%5Bsize%5D=20"
    },
    "data": [
        {
            "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "name": "Autumn sale",
            "image": "/data/banner/autumn.jpg",
            "url": "https://shop.example.com/sale",
            "target": "_self",
            "html": null,
            "type": "banner",
            "sort": 0,
            "status": 1,
            "store_id": "1",
            "created_at": "2026-10-31T08:00:00+07:00",
            "updated_at": "2026-10-31T08:00:00+07:00",
            "click": 57
        }
    ]
}

Errors: validation_failed

Get one CMS page (admin) — GET /api/v2/core/page/detail/{id}

Returns one CMS page of the admin's store with its HTML body, in the language given by ?lang=. Requires access to the Pages screen.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Pages (gp247_admin/page).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since front 3.3.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/page/detail/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: Page

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "alias": "about-us",
        "image": null,
        "name": "About us",
        "keyword": "about",
        "description": "Who we are.",
        "content": "<p>Who we are.</p>",
        "status": 1,
        "store_id": "1",
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00"
    }
}

Errors: not_found

List CMS pages (admin) — GET /api/v2/core/page/list

Returns the CMS pages of the admin's store, page by page, without the HTML body. Text fields are in the language given by ?lang= (site default otherwise). Requires access to the Pages screen.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Pages (gp247_admin/page).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since front 3.3.0

Parameters

Name In Type Meaning
page[number] query integer Page to read, from 1.
page[size] query integer Rows per page (default 20, max 100).
updated_since query string (date-time) Sync mode (since core 3.7.0): ISO-8601 date-time, e.g. 2026-10-31T08:00:00+07:00 (date only or no offset = site timezone). Returns rows with updated_at >= updated_since, oldest change first (updated_at, then id). Cannot be combined with sort or page[number] (422)
page[after] query string Sync mode only: cursor from meta.next_after of the previous page; any other value = 422
filter query object filter[<name>]=value — allowed names per resource, see api-introduction section 8; unknown name = 422
sort query string <name> ascending, -<name> descending; unknown name = 422
q query string Search term
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/page/list" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Page — with meta (paging) and links.

{
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 135,
        "last_page": 7,
        "next_after": "eyJ0IjoiMjAyNi0xMC0zMSAwODowMDowMCIsImsiOiI5ZjBjIn0",
        "has_more": true,
        "sync_until": "2026-10-31T08:00:00+07:00"
    },
    "links": {
        "first": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=1&page%5Bsize%5D=20",
        "last": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=7&page%5Bsize%5D=20",
        "prev": null,
        "next": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=2&page%5Bsize%5D=20"
    },
    "data": [
        {
            "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "alias": "about-us",
            "image": null,
            "name": "About us",
            "keyword": "about",
            "description": "Who we are.",
            "content": "<p>Who we are.</p>",
            "status": 1,
            "store_id": "1",
            "created_at": "2026-10-31T08:00:00+07:00",
            "updated_at": "2026-10-31T08:00:00+07:00"
        }
    ]
}

Errors: validation_failed

Admin · Customers

Customer accounts and locking or unlocking an account.

Get one customer (admin) — GET /api/v2/core/customer/detail/{id}

Returns one customer of the admin's store with the admin-only fields. A record of another store answers 404. Accepts fields[customer]=a,b.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Customers (gp247_admin/customer).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/customer/detail/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: Customer

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "first_name": "An",
        "last_name": "Nguyen",
        "first_name_kana": null,
        "last_name_kana": null,
        "email": "an@example.com",
        "phone": "0901234567",
        "sex": 1,
        "birthday": "1990-05-20",
        "company": null,
        "country": "VN",
        "postcode": "700000",
        "city": "Ho Chi Minh City",
        "district": "District 1",
        "ward": "Ben Nghe",
        "address1": "1 Le Loi",
        "address2": null,
        "address3": null,
        "status": 1,
        "group": 1,
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00",
        "store_id": "1",
        "email_verified_at": "2026-10-01 08:00:00"
    }
}

Errors: not_found · validation_failed

List customers (admin) — GET /api/v2/core/customer/list

Returns the customers of the admin's store, page by page. Requires an admin token allowed to open the matching admin screen. Includes the admin-only fields store_id and email_verified_at; never the password. Filter by status or group, sort by created_at or email, search by e-mail, phone or name. Accepts fields[customer]=a,b to return only some fields. Supports updated_since=<ISO 8601> sync mode: oldest change first, paged with page[after] (meta then has per_page, next_after, has_more, sync_until; links only next).

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Customers (gp247_admin/customer).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
page[number] query integer Page to read, from 1.
page[size] query integer Rows per page (default 20, max 100).
updated_since query string (date-time) Sync mode (since core 3.7.0): ISO-8601 date-time, e.g. 2026-10-31T08:00:00+07:00 (date only or no offset = site timezone). Returns rows with updated_at >= updated_since, oldest change first (updated_at, then id). Cannot be combined with sort or page[number] (422)
page[after] query string Sync mode only: cursor from meta.next_after of the previous page; any other value = 422
filter query object filter[<name>]=value — allowed names per resource, see api-introduction section 8; unknown name = 422
sort query string <name> ascending, -<name> descending; unknown name = 422
q query string Search term
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/customer/list" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Customer — with meta (paging) and links.

{
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 135,
        "last_page": 7,
        "next_after": "eyJ0IjoiMjAyNi0xMC0zMSAwODowMDowMCIsImsiOiI5ZjBjIn0",
        "has_more": true,
        "sync_until": "2026-10-31T08:00:00+07:00"
    },
    "links": {
        "first": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=1&page%5Bsize%5D=20",
        "last": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=7&page%5Bsize%5D=20",
        "prev": null,
        "next": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=2&page%5Bsize%5D=20"
    },
    "data": [
        {
            "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "first_name": "An",
            "last_name": "Nguyen",
            "first_name_kana": null,
            "last_name_kana": null,
            "email": "an@example.com",
            "phone": "0901234567",
            "sex": 1,
            "birthday": "1990-05-20",
            "company": null,
            "country": "VN",
            "postcode": "700000",
            "city": "Ho Chi Minh City",
            "district": "District 1",
            "ward": "Ben Nghe",
            "address1": "1 Le Loi",
            "address2": null,
            "address3": null,
            "status": 1,
            "group": 1,
            "created_at": "2026-10-31T08:00:00+07:00",
            "updated_at": "2026-10-31T08:00:00+07:00",
            "store_id": "1",
            "email_verified_at": "2026-10-01 08:00:00"
        }
    ]
}

Errors: validation_failed

Lock or unlock a customer — PATCH /api/v2/core/customer/{id}

Sets the status of a customer of the admin's store: 0 locks the account at once (API and storefront), 1 unlocks it. Any other field is refused with 422. Answers the customer with admin-only fields. Idempotency-Key optional.

Sign-in Admin token (Bearer).
Permission Write access to the admin screen Customers (gp247_admin/customer).
Since shop 3.6.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
Idempotency-Key header string Optional; 8-255 printable characters (e.g. a UUID). A retry with the same key and body answers the first result

Request body: AdminCustomerUpdateRequest

Example request

curl -X PATCH "https://shop.example.com/api/v2/core/customer/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"status":0}'

Response 200 — data: Customer

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "first_name": "An",
        "last_name": "Nguyen",
        "first_name_kana": null,
        "last_name_kana": null,
        "email": "an@example.com",
        "phone": "0901234567",
        "sex": 1,
        "birthday": "1990-05-20",
        "company": null,
        "country": "VN",
        "postcode": "700000",
        "city": "Ho Chi Minh City",
        "district": "District 1",
        "ward": "Ben Nghe",
        "address1": "1 Le Loi",
        "address2": null,
        "address3": null,
        "status": 1,
        "group": 1,
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00",
        "store_id": "1",
        "email_verified_at": "2026-10-01 08:00:00"
    }
}

Errors: not_found · validation_failed · forbidden · idempotency_key_required · idempotency_key_reused · idempotency_in_progress · idempotency_unavailable

Admin · Orders

Orders, their status, delivery details and notes.

Get one order (admin) — GET /api/v2/core/order/detail/{id}

Returns one order of the admin's store with the admin-only fields. A record of another store answers 404. Accepts fields[order]=a,b and include=transactions,histories.

Sign-in Admin token (Bearer).
Permission Read access to the admin order detail screen (gp247_admin/order/detail/{id}).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.
include query string Comma-separated related records to embed (one level, at most 3): transactions (payment ledger), histories (processing history, plain text). Anything else = 422. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/order/detail/123" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: Order

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "customer_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "status": 1,
        "payment_status": 1,
        "shipping_status": 1,
        "currency": "VND",
        "exchange_rate": 1,
        "subtotal": 360000,
        "tax": 36000,
        "shipping": 30000,
        "discount": 0,
        "other_fee": 0,
        "total": 426000,
        "received": 0,
        "balance": 426000,
        "first_name": "An",
        "last_name": "Nguyen",
        "email": "an@example.com",
        "phone": "0901234567",
        "company": null,
        "country": "VN",
        "postcode": "700000",
        "city": "Ho Chi Minh City",
        "district": "District 1",
        "ward": "Ben Nghe",
        "address1": "1 Le Loi",
        "address2": null,
        "address3": null,
        "comment": "Call before delivery",
        "payment_method": "Cash",
        "shipping_method": "ShippingStandard",
        "store_id": "1",
        "details": [],
        "totals": [],
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00",
        "ip": "203.0.113.5",
        "user_agent": "MyShopApp/1.0",
        "device_type": "phone",
        "domain": "shop.example.com",
        "transaction": null
    }
}

Errors: not_found · validation_failed

Change order status — POST /api/v2/core/order/{id}/status

Sets the order status exactly as the admin order screen does: cancelling returns stock, re-opening a cancelled order takes it back (refused with 409 when stock is short) and a history line is written. Answers the order as order/detail does. An Idempotency-Key header is optional; a retry with the same key replays the first answer.

Sign-in Admin token (Bearer).
Permission Write access to the admin screen Orders (gp247_admin/order).
Since shop 3.6.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
Idempotency-Key header string Optional; 8-255 printable characters (e.g. a UUID). A retry with the same key and body answers the first result

Request body: AdminOrderStatusRequest

Example request

curl -X POST "https://shop.example.com/api/v2/core/order/123/status" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"status":0}'

Response 200 — data: Order

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "customer_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "status": 1,
        "payment_status": 1,
        "shipping_status": 1,
        "currency": "VND",
        "exchange_rate": 1,
        "subtotal": 360000,
        "tax": 36000,
        "shipping": 30000,
        "discount": 0,
        "other_fee": 0,
        "total": 426000,
        "received": 0,
        "balance": 426000,
        "first_name": "An",
        "last_name": "Nguyen",
        "email": "an@example.com",
        "phone": "0901234567",
        "company": null,
        "country": "VN",
        "postcode": "700000",
        "city": "Ho Chi Minh City",
        "district": "District 1",
        "ward": "Ben Nghe",
        "address1": "1 Le Loi",
        "address2": null,
        "address3": null,
        "comment": "Call before delivery",
        "payment_method": "Cash",
        "shipping_method": "ShippingStandard",
        "store_id": "1",
        "details": [],
        "totals": [],
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00",
        "ip": "203.0.113.5",
        "user_agent": "MyShopApp/1.0",
        "device_type": "phone",
        "domain": "shop.example.com",
        "transaction": null
    }
}

Errors: not_found · validation_failed · forbidden · idempotency_key_required · idempotency_key_reused · idempotency_in_progress · idempotency_unavailable · admin.order.reopen_blocked_stock

Set shipping status or tracking — POST /api/v2/core/order/{id}/shipping

Sets the shipping status and/or records a tracking number (and URL) as the order's manual shipment. The payment status cannot be written here. Answers the updated order. Idempotency-Key optional.

Sign-in Admin token (Bearer).
Permission Write access to the admin screen Orders (gp247_admin/order).
Since shop 3.6.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
Idempotency-Key header string Optional; 8-255 printable characters (e.g. a UUID). A retry with the same key and body answers the first result

Request body: AdminOrderShippingRequest

Example request

curl -X POST "https://shop.example.com/api/v2/core/order/123/shipping" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"shipping_status":0,"tracking_number":"","tracking_url":""}'

Response 200 — data: Order

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "customer_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "status": 1,
        "payment_status": 1,
        "shipping_status": 1,
        "currency": "VND",
        "exchange_rate": 1,
        "subtotal": 360000,
        "tax": 36000,
        "shipping": 30000,
        "discount": 0,
        "other_fee": 0,
        "total": 426000,
        "received": 0,
        "balance": 426000,
        "first_name": "An",
        "last_name": "Nguyen",
        "email": "an@example.com",
        "phone": "0901234567",
        "company": null,
        "country": "VN",
        "postcode": "700000",
        "city": "Ho Chi Minh City",
        "district": "District 1",
        "ward": "Ben Nghe",
        "address1": "1 Le Loi",
        "address2": null,
        "address3": null,
        "comment": "Call before delivery",
        "payment_method": "Cash",
        "shipping_method": "ShippingStandard",
        "store_id": "1",
        "details": [],
        "totals": [],
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00",
        "ip": "203.0.113.5",
        "user_agent": "MyShopApp/1.0",
        "device_type": "phone",
        "domain": "shop.example.com",
        "transaction": null
    }
}

Errors: not_found · validation_failed · forbidden · idempotency_key_required · idempotency_key_reused · idempotency_in_progress · idempotency_unavailable · admin.order.shipping_status_invalid

Add an order note — POST /api/v2/core/order/{id}/notes

Adds a note (up to 1000 characters) to the order history, marked as written through the API. Answers the order. Idempotency-Key optional.

Sign-in Admin token (Bearer).
Permission Write access to the admin screen Orders (gp247_admin/order).
Since shop 3.6.0

Parameters

Name In Type Meaning
id (required) path string Id of the record (UUID).
Idempotency-Key header string Optional; 8-255 printable characters (e.g. a UUID). A retry with the same key and body answers the first result

Request body: AdminOrderNotesRequest

Example request

curl -X POST "https://shop.example.com/api/v2/core/order/123/notes" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"content":""}'

Response 200 — data: Order

{
    "data": {
        "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "customer_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
        "status": 1,
        "payment_status": 1,
        "shipping_status": 1,
        "currency": "VND",
        "exchange_rate": 1,
        "subtotal": 360000,
        "tax": 36000,
        "shipping": 30000,
        "discount": 0,
        "other_fee": 0,
        "total": 426000,
        "received": 0,
        "balance": 426000,
        "first_name": "An",
        "last_name": "Nguyen",
        "email": "an@example.com",
        "phone": "0901234567",
        "company": null,
        "country": "VN",
        "postcode": "700000",
        "city": "Ho Chi Minh City",
        "district": "District 1",
        "ward": "Ben Nghe",
        "address1": "1 Le Loi",
        "address2": null,
        "address3": null,
        "comment": "Call before delivery",
        "payment_method": "Cash",
        "shipping_method": "ShippingStandard",
        "store_id": "1",
        "details": [],
        "totals": [],
        "created_at": "2026-10-31T08:00:00+07:00",
        "updated_at": "2026-10-31T08:00:00+07:00",
        "ip": "203.0.113.5",
        "user_agent": "MyShopApp/1.0",
        "device_type": "phone",
        "domain": "shop.example.com",
        "transaction": null
    }
}

Errors: not_found · validation_failed · forbidden · idempotency_key_required · idempotency_key_reused · idempotency_in_progress · idempotency_unavailable

List orders (admin) — GET /api/v2/core/order/list

Returns the orders of the admin's store, page by page. Requires an admin token allowed to open the matching admin screen. Each order carries its lines (details) and totals, plus admin-only request data (ip, user_agent, device_type, domain, transaction). Filters: status, payment_status, shipping_status, customer_id; sort by created_at or total; search by order id, e-mail or phone; include=transactions,histories. Accepts fields[order]=a,b to return only some fields. Supports updated_since=<ISO 8601> sync mode: oldest change first, paged with page[after] (meta then has per_page, next_after, has_more, sync_until; links only next).

Sign-in Admin token (Bearer).
Permission Read access to the admin screen Orders (gp247_admin/order).
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since shop 3.3.0

Parameters

Name In Type Meaning
page[number] query integer Page to read, from 1.
page[size] query integer Rows per page (default 20, max 100).
updated_since query string (date-time) Sync mode (since core 3.7.0): ISO-8601 date-time, e.g. 2026-10-31T08:00:00+07:00 (date only or no offset = site timezone). Returns rows with updated_at >= updated_since, oldest change first (updated_at, then id). Cannot be combined with sort or page[number] (422)
page[after] query string Sync mode only: cursor from meta.next_after of the previous page; any other value = 422
filter query object filter[<name>]=value — allowed names per resource, see api-introduction section 8; unknown name = 422
sort query string <name> ascending, -<name> descending; unknown name = 422
q query string Search term
lang query string Language of names/descriptions
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.
fields query object fields[<type>]=a,b keeps only those fields (and id) of the record and of included records. Unknown type or field = 422. Without it the body is unchanged. Since core 3.8.0.
include query string Comma-separated related records to embed (one level, at most 3): transactions (payment ledger), histories (processing history, plain text). Anything else = 422. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/order/list" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Order — with meta (paging) and links.

{
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 135,
        "last_page": 7,
        "next_after": "eyJ0IjoiMjAyNi0xMC0zMSAwODowMDowMCIsImsiOiI5ZjBjIn0",
        "has_more": true,
        "sync_until": "2026-10-31T08:00:00+07:00"
    },
    "links": {
        "first": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=1&page%5Bsize%5D=20",
        "last": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=7&page%5Bsize%5D=20",
        "prev": null,
        "next": "https://shop.example.com/api/v2/front/product/list?page%5Bnumber%5D=2&page%5Bsize%5D=20"
    },
    "data": [
        {
            "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "customer_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "status": 1,
            "payment_status": 1,
            "shipping_status": 1,
            "currency": "VND",
            "exchange_rate": 1,
            "subtotal": 360000,
            "tax": 36000,
            "shipping": 30000,
            "discount": 0,
            "other_fee": 0,
            "total": 426000,
            "received": 0,
            "balance": 426000,
            "first_name": "An",
            "last_name": "Nguyen",
            "email": "an@example.com",
            "phone": "0901234567",
            "company": null,
            "country": "VN",
            "postcode": "700000",
            "city": "Ho Chi Minh City",
            "district": "District 1",
            "ward": "Ben Nghe",
            "address1": "1 Le Loi",
            "address2": null,
            "address3": null,
            "comment": "Call before delivery",
            "payment_method": "Cash",
            "shipping_method": "ShippingStandard",
            "store_id": "1",
            "details": [],
            "totals": [],
            "created_at": "2026-10-31T08:00:00+07:00",
            "updated_at": "2026-10-31T08:00:00+07:00",
            "ip": "203.0.113.5",
            "user_agent": "MyShopApp/1.0",
            "device_type": "phone",
            "domain": "shop.example.com",
            "transaction": null
        }
    ]
}

Errors: validation_failed

Admin · Sync

Event log for ERP / sync tools: every change of orders, stock, products and customers, read by cursor.

Read the event log — GET /api/v2/core/events

Returns change events (orders, stock, products, customers) oldest first, for ERP and sync tools. Send ?after=<last id handled> to continue; page[size] default 100, max 500; filter[type]=a,b narrows the types. Only types of screens the admin may open and the admin's store are returned; events younger than a few seconds are held back. 409 when the event log is off, 410 when the cursor points to cleaned events.

Sign-in Admin token (Bearer).
Permission Read access to the admin screen of each event type returned: Orders for order., Products for product. and stock., Customers for customer..
Caching ETag — send If-None-Match to get 304 when nothing changed.
Since core 3.7.0

Parameters

Name In Type Meaning
after query integer id of the last event the reader handled; returns the events after it. Omitted = from the oldest event still kept
filter[type] query string Comma-separated event types (<resource>.<action>); only narrows the types the admin may read. gp247/shop 3.6.0 types: order.created, order.status_changed, order.payment_status_changed, stock.changed, product.updated, product.deleted, customer.created, customer.updated
page[size] query integer Rows per page (default 20, max 100).
If-None-Match header string ETag of a previous answer; 304 with an empty body when nothing changed. Since core 3.8.0.

Example request

curl "https://shop.example.com/api/v2/core/events" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <admin-token>"

Response 200 — data: list of Event

{
    "data": [
        {
            "id": 1024,
            "type": "order.status_changed",
            "subject_id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f",
            "store_id": "1",
            "source": "admin",
            "actor": {
                "type": "admin",
                "id": "9f0c2a3e-6b1d-4c5e-8a7f-2d3b4c5d6e7f"
            },
            "data": {
                "field": "status",
                "from": 1,
                "to": 2
            },
            "occurred_at": "2026-10-31T08:00:00+07:00"
        }
    ],
    "meta": {
        "per_page": 100,
        "next_after": 4512,
        "has_more": false
    }
}

Errors: event_log_disabled · cursor_expired · validation_failed · forbidden

Data objects

Fields of the objects the endpoints above send and return. Dates are ISO 8601 strings; money is a number in the currency of the record.

AdminInfo

Field Type Meaning
id string Admin user id.
username string Sign-in name.
name string | null Display name.
email string | null E-mail.
avatar string | null Avatar path.
status integer 1 = active.
roles list of string Role slugs.
created_at string | null Creation time (ISO 8601).
updated_at string | null Last change time (ISO 8601).

SessionToken

Field Type Meaning
access_token string Bearer token to send as Authorization: Bearer <token>.
token_type string Always Bearer.
scopes list of string Abilities of the token.
expires_at string | null When the access token expires, 'Y-m-d H:i:s' in the site's timezone (not ISO 8601).
expires_in integer | null Seconds until the access token expires.
session_id string API session id; present once the site has run gp247:update (session tables exist).
refresh_token string Only when with_refresh=true: single-use refresh token, shown once.
refresh_expires_at string Only when with_refresh=true: when the refresh token expires, 'Y-m-d H:i:s'.
cart_merge object Customer sign-in only, when an X-Cart-Token guest cart was sent: {merged, dropped} line counts.

AdminLoginV2

Field Type Meaning
username string Username of the administrator. (required)
password string Password of the administrator. (required)
remember_me boolean Longer-lived token.
with_refresh boolean Also issue a rotating refresh token; the access token then lives 60 minutes
device_name string Shown in the sessions list

AdminLogoutResult

Field Type Meaning
revoked boolean Always true.

LoginChallengeAnswer

Plus the fields defined by the challenge plugin (e.g. code)

Field Type Meaning
ticket string Ticket from the challenge_required answer of login. (required)

RefreshRequest

Field Type Meaning
refresh_token string Refresh token from login or from the previous refresh; each one works once. (required)

Session

Field Type Meaning
id string Session id.
name string | null Device name sent at sign-in, else the user agent.
ip string | null IP address at sign-in.
created_at string | null Sign-in time (ISO 8601).
last_used_at string | null Last use (ISO 8601).
refreshable boolean Whether the session has a refresh token.
refresh_expires_at string | null When the refresh window ends (ISO 8601).
current boolean True for the session of the calling token.

AdminSessionsDeleteResult

Field Type Meaning
revoked boolean Always true.

Brand

Field Type Meaning
id string Brand id.
name string Brand name.
alias string URL slug.
image string | null Logo path.
url string | null Brand website.
sort integer Sort order.
status integer 1 = enabled.
store_id string | null Store id.
created_at string | null Creation time (ISO 8601).
updated_at string | null Last change time (ISO 8601).

Category

Field Type Meaning
id string Category id.
alias string URL slug.
name string | null Name in the requested language.
keyword string | null SEO keywords in the requested language.
description string | null Description in the requested language.
image string | null Image path.
parent string | null Parent category id.
top integer 1 = shown in the top menu.
sort integer Sort order.
status integer 1 = enabled.
store_id string | null Store id.
created_at string | null Creation time (ISO 8601).
updated_at string | null Last change time (ISO 8601).

Product

Field Type Meaning
id string Product id (UUID).
sku string Stock keeping unit code.
alias string URL slug of the product.
name string | null Product name in the requested language (falls back to the first language).
keyword string | null SEO keywords in the requested language.
description string | null Short description in the requested language.
content string | null HTML body in the requested language; detail answers only (not in lists). (detail only)
image string | null Main image path as stored.
images list of string Paths of the extra images; filled on detail answers or with include=images, empty array in lists otherwise.
price number | null List price; null when the store hides prices on the storefront (admins always see it).
price_final number | null Price the storefront charges (promotion applied); null when the store hides prices.
tax_id string | null Tax rule id; '0' = no tax, 'auto' = the store's default tax.
kind integer Product kind: 0 single, 1 build (made of components), 2 group.
product_type string | null Product type, e.g. physical or digital.
brand_id string | null Brand id.
category_ids list of string Ids of the product's categories (storefront: only categories the storefront shows).
minimum number Minimum quantity per order.
weight number Weight.
weight_class string | null Weight unit.
length number Length.
width number Width.
height number Height.
length_class string | null Length unit.
date_available string | null Date the product becomes available (Y-m-d, raw column value).
store_id string | null Store that owns the product.
created_at string | null Creation time (ISO 8601).
updated_at string | null Last change time (ISO 8601).
image_sizes object Absolute URLs of the main image: {original, thumb} (site placeholder when there is no image).
stock_status string in_stock or out_of_stock; always in_stock when the shop does not track stock or sells out of stock.
attributes list of ProductAttributeGroup Attribute groups the buyer must choose to add the product to the cart.
cost number admin only. Cost price. (admin only)
stock number admin only. Units in stock. (admin only)
sold number admin only. Units sold. (admin only)
status integer admin only. 1 = enabled, 0 = disabled. (admin only)
approve integer admin only. Moderation flag: 1 = approved. (admin only)
supplier_id string | null admin only. Supplier id. (admin only)
view integer admin only. Number of views. (admin only)
brand Brand Only with include=brand: the brand (storefront: only an enabled brand). (only with include brand)
categories list of Category Only with include=categories: the categories in full. (only with include categories)

AdminProductUpdateRequest

At least one of price / cost / status; nothing else

Field Type Meaning
price number Selling price; refused (422) when the store turned the price field off
cost number Cost price; refused (422) when the store turned the cost field off
status integer 1 = on sale, 0 = hidden.

Supplier

Field Type Meaning
id string Supplier id.
name string Supplier name.
alias string URL slug.
email string | null Contact e-mail.
phone string | null Contact phone.
image string | null Logo path.
address string | null Postal address.
url string | null Website.
sort integer Sort order.
status integer 1 = enabled.
store_id string | null Store id.
created_at string | null Creation time (ISO 8601).
updated_at string | null Last change time (ISO 8601).

AdminProductStockRequest

Exactly one of delta / set (both or neither: 422 validation_failed)

Field Type Meaning
delta number Receive (+) or issue (-) goods, not 0; whole numbers unless decimal quantities are allowed in the product settings. Atomic: an order placed at the same moment loses nothing. Never below zero (422 stock_would_be_negative, nothing moves). The sold counter is not touched
set number Set the stock outright after a stock count; administrator role only (others: 403)

AdminProductStockResult

Field Type Meaning
id string Product id.
sku string Product SKU.
stock number Stock after the move (whole number when it has no decimals).

AdminStockBatchRequest

Field Type Meaning
items list of object More than 100 lines or a malformed line: 422, nothing applied (required)

AdminStockBatchResult

Field Type Meaning
results list of StockBatchResult One result per line, in request order.
ok integer Lines applied.
failed integer Lines refused.
Field Type Meaning
id string Banner id.
name string | null Banner name.
image string | null Image path.
url string | null Link target.
target string | null Link target window, e.g. _self or _blank.
html string | null Optional HTML content.
type string Banner position/type code.
sort integer Sort order.
status integer 1 = enabled.
store_id string | null Store id.
created_at string | null Creation time (ISO 8601).
updated_at string | null Last change time (ISO 8601).
click integer admin only. Number of clicks. (admin only)

Page

Field Type Meaning
id string Page id.
alias string URL slug.
image string | null Image path.
name string | null Title in the requested language.
keyword string | null SEO keywords.
description string | null Short description.
content string | null HTML body; detail answers only (not in lists). (detail only)
status integer 1 = enabled.
store_id string | null Store id.
created_at string | null Creation time (ISO 8601).
updated_at string | null Last change time (ISO 8601).

Customer

Field Type Meaning
id string Customer id.
first_name string | null First name.
last_name string | null Last name.
first_name_kana string | null First name in kana (Japanese stores).
last_name_kana string | null Last name in kana (Japanese stores).
email string E-mail address (sign-in name).
phone string | null Phone number.
sex integer | null 0 = female, 1 = male (raw column value).
birthday string | null Birthday (Y-m-d, raw column value).
company string | null Company.
country string | null Country code.
postcode string | null Postcode.
city string | null City.
district string | null District.
ward string | null Ward.
address1 string | null Address line 1.
address2 string | null Address line 2.
address3 string | null Address line 3.
status integer 1 = active, 0 = locked.
group integer Customer group (raw column value).
created_at string | null Creation time (ISO 8601).
updated_at string | null Last change time (ISO 8601).
store_id string | null admin only. Store of the account. (admin only)
email_verified_at string | null admin only. When the e-mail was verified, raw 'Y-m-d H:i:s' value (not ISO 8601); null if never. (admin only)

AdminCustomerUpdateRequest

Only status; nothing else

Field Type Meaning
status integer 0 = lock, 1 = unlock (required)

Order

Field Type Meaning
id string Order id.
customer_id string | null Customer id ('0' or empty for a guest order).
status integer Order status id (statuses configured on the admin order screen).
payment_status integer Payment status id.
shipping_status integer Shipping status id.
currency string Currency of the order.
exchange_rate number Exchange rate used for the order.
subtotal number Sum of the lines.
tax number Tax.
shipping number Shipping fee.
discount number Discount.
other_fee number Other fees.
total number Amount to pay.
received number Amount received so far.
balance number Amount still due.
first_name string | null Delivery first name.
last_name string | null Delivery last name.
email string | null Buyer e-mail.
phone string | null Buyer phone.
company string | null Company.
country string | null Country code.
postcode string | null Postcode.
city string | null City.
district string | null District.
ward string | null Ward.
address1 string | null Address line 1.
address2 string | null Address line 2.
address3 string | null Address line 3.
comment string | null Buyer's note.
payment_method string | null Payment plugin key.
shipping_method string | null Shipping plugin key.
store_id string | null Store of the order.
details list of OrderLine Order lines.
totals list of OrderTotal Total rows in display order.
created_at string | null Creation time (ISO 8601).
updated_at string | null Last change time (ISO 8601).
ip string | null admin only. IP address the order came from. (admin only)
user_agent string | null admin only. Browser / app user agent. (admin only)
device_type string | null admin only. Device type (desktop, phone, tablet, other). (admin only)
domain string | null admin only. Site domain the order was placed on. (admin only)
transaction string | null admin only. Legacy transaction reference. (admin only)
transactions list of OrderTransaction admin only, with include=transactions: money movements of the order. (admin only, only with include transactions)
histories list of OrderHistory admin only, with include=histories: order history lines (plain text). (admin only, only with include histories)

AdminOrderStatusRequest

Field Type Meaning
status integer Id of one of the site's order statuses. Cancelling returns stock to inventory, reopening takes it back; a finished or cancelled order can be reopened. The current status answers 200 and writes nothing (required)

AdminOrderShippingRequest

At least one of shipping_status / tracking_number. payment_status is refused (422): it follows the order's payments

Field Type Meaning
shipping_status integer Id of one of the site's shipping statuses; a change adds an order history line
tracking_number string Kept as the order's manual shipment (one per order; another number updates it), shown on the admin order screen
tracking_url string (uri) http(s) address; needs tracking_number

AdminOrderNotesRequest

Field Type Meaning
content string Saved with the author and the label [API]; shown as plain text (markup escaped) (required)

Event

Field Type Meaning
id integer Event id; pass the last one handled as ?after= to continue.
type string Event type, e.g. order.created, order.status_changed, order.payment_status_changed, stock.changed, product.updated, product.deleted, customer.created, customer.updated.
subject_id string Id of the record the event is about.
store_id string | null Store of the record.
source string Where the change came from: api, admin, web or system.
actor object | null Who made the change: {type: admin|customer, id}; null when unknown (system).
data object Fields declared for the type (e.g. {field, from, to} for order.status_changed); empty object when none.
occurred_at string When it happened (ISO 8601).

EventListMeta

Field Type Meaning
per_page integer Page size.
next_after integer | null Id of the last event of this page; send it as after= to read on. Null when the page is empty.
has_more boolean Whether more events are ready to read now.

ProductAttributeGroup

Field Type Meaning
group_id string Attribute group id; the cart takes the choice as options[group_id].
name string Group name, e.g. Color.
required boolean Always true: every group must be chosen.
options list of object Choices of the group: {value, add_price}; add_price is the surcharge, null when prices are hidden.

StockBatchResult

Field Type Meaning
id string Product id (the id sent, or the id found by SKU).
sku string Only when the line named the product by SKU.
ok boolean Whether this line was applied.
stock number Stock after the move (when ok).
code string When not ok: not_found, sku_not_found, sku_ambiguous, forbidden, stock_managed_by_components, stock_would_be_negative.
msg string When not ok: human-readable reason.

OrderLine

Field Type Meaning
id string Line id.
product_id string Product id.
sku string | null SKU at order time.
name string | null Product name at order time.
price number Unit price.
qty number Quantity.
discount number Line discount.
tax number Line tax.
tax_rate number Tax rate in percent.
total_price number Line total.
attribute string | null Chosen attributes as a JSON-encoded string {group_id: 'name__price[__slug]'}, raw column value.

OrderTotal

Field Type Meaning
code string Row code, e.g. subtotal, tax, shipping, discount, total.
title string Row label.
value number Amount.
text string Amount formatted for display.

OrderTransaction

Field Type Meaning
id string Transaction id.
type string Kind of money movement (e.g. payment, refund).
amount number Amount.
currency string Currency.
method string | null Payment method key.
gateway_transaction_id string | null Reference at the payment gateway.
paid_at string | null When it was paid (ISO 8601).
created_at string | null When it was recorded (ISO 8601).

OrderHistory

Field Type Meaning
id string History line id.
content string Text of the history line (HTML removed).
order_status_id integer Order status at the time of the line.
admin_id string | null Admin who wrote it.
customer_id string | null Customer who wrote it.
created_at string | null When it was written (ISO 8601).

📅 Last updated: 2026-11-03 · ✍️ Author: GP247