Skip to main content

Vinaway API Documentation

Integrate your e-commerce store with Vinaway's fulfillment network. Automate order processing, track shipments, and manage products directly from your application.

Introduction

The Vinaway API is organized around REST. Our API has predictable resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.

Production: https://api.vinaway.io/api

Development: https://dev.api.vinaway.io/api

Authentication

Authenticate your API requests using a Bearer token. To obtain a token, you need to exchange your email and password.

POST /token

Request Body

{
    "email": "your_email@example.com",
    "password": "your_password"
}

Response

{
    "access_token": "76|5lrXZKyBRTRL8pDvpUBNZ...",
    "token_type": "Bearer",
    "expires_in": 18000
}

Create Order

Create a new production order. This endpoint accepts a list of items to be fulfilled.

POST /orders

Parameters

Field Type Required Description
type integer Yes Order type (1: Production)
external_order_id string No Your unique identifier for this order. Max 255 characters, and must be unique per seller among orders that are not cancelled
production_line_id integer Yes ID of the production line (e.g., 1 for Standard). The production line must support shipping to the order's country
note_seller string No Free-text note for the production team. Max 1000 characters
shipping_label string No URL of an existing shipping label. When provided, the customer and address fields below are not required, and the customer information is read from the label instead
customer_name string Conditional Name of the customer. Required when shipping_label is not provided. Max 255 characters
email string No Customer email address
tel string No Customer phone number
address1 string Conditional Street address. Required when shipping_label is not provided. Max 255 characters
address2 string No Additional address line (apartment, suite, unit…). Max 255 characters
city string Conditional City. Required when shipping_label is not provided. Max 255 characters
state string Conditional State code (e.g. NY) or state name. Resolved against the given country. Required when the country is US and shipping_label is not provided
zip string Conditional ZIP / postal code, max 10 characters. Required when shipping_label is not provided
country string Yes Country code (e.g. US). Looked up to resolve the country_id; an unknown or missing code fails with "Country not found"
vat_ioss string No Customer VAT / tax number
items array Yes Array of items to produce. At least one item is required

Item Fields

Each entry of the "items" array describes one product to produce.

Field Type Required Description
items[].product_id integer Yes ID of the product to produce. Must exist in the catalog
items[].product_sku_id integer No ID of the product SKU (variant: size, colour…). Must be an existing, non-deleted SKU of the product
items[].quantity integer Yes Quantity to produce. Between 1 and 1000
items[].mockup1 string No URL of the first mockup image of the item
items[].mockup2 string No URL of the second mockup image of the item
items[].productSurfaces array No Design files applied to each print surface of the item. See "Product Surface Fields" below

Product Surface Fields

Each item in the "items" array may contain a "productSurfaces" array. Each product surface describes the design files applied to one print surface of the product.

Field Type Required Description
product_surface_id integer Yes ID of the product surface the design is applied to
design_png string No URL of the 2D design image (PNG). When provided, the image dimensions must exactly match the width and height configured for the product surface (e.g. 4500x5400 px)
design_emb string No URL of the machine embroidery file (EMB format)
design_dst string No URL of the machine embroidery file (DST format, Tajima)
screenshot string No URL of a screenshot/preview image of the design, e.g. a preview of the mockup or embroidery layout
google_drive_folder_url string No URL of a publicly accessible Google Drive folder containing the design files (design_png / design_dst / design_emb). Use this instead of uploading each file URL when your designs are stored in Drive
Design requirements
  • Each item must include at least one of: mockup1, mockup2, a Google Drive folder URL, or design files (design_png / design_dst / design_emb) on at least one product surface.
  • If no mockup is provided, the Google Drive folder (when used) must be publicly accessible and contain design files.
  • When design_png is validated against the product surface dimensions, the image is downloaded and checked; make sure the URL is publicly reachable.

Example Request

{
    "type": 1,
    "external_order_id": "ORD-2024-001",
    "production_line_id": 1,
    "note_seller": "Gift order, please pack carefully.",
    "customer_name": "John Doe",
    "address1": "123 Main St",
    "city": "New York",
    "zip": "10001",
    "country": "US",
    "state": "NY",
    "items": [
        {
            "product_id": 1,
            "product_sku_id": 1,
            "quantity": 1,
            "mockup1": "https://example.com/mockup-front.png",
            "productSurfaces": [
                {
                    "product_surface_id": 3,
                    "design_png": "https://example.com/design.png",
                    "design_emb": "https://example.com/design.emb",
                    "design_dst": "https://example.com/design.dst",
                    "screenshot": "https://example.com/design-preview.png"
                }
            ]
        }
    ]
}

Alternatively, when your design files are stored in Google Drive, you can send the folder URL instead of individual file URLs. The folder must be publicly accessible and contain the design files (design_png / design_dst / design_emb).

{
    "type": 1,
    "production_line_id": 1,
    "customer_name": "John Doe",
    "items": [
        {
            "product_id": 1,
            "product_sku_id": 1,
            "quantity": 1,
            "productSurfaces": [
                {
                    "product_surface_id": 3,
                    "google_drive_folder_url": "https://drive.google.com/drive/folders/1AbC123Xyz"
                }
            ]
        }
    ]
}

Success Response

The created order is returned — the same order object as the Get Order endpoint — with "success" and "message" added.

{
    "internal_order_id": "VN7PIEA4FA5U",
    "external_order_id": "ORD-2024-001",
    "type": 1,
    "status": 0,
    "amount_subtotal": 2470,
    "amount_shipping": 0,
    "amount_total": 2470,
    "customer_name": "John Doe",
    "address1": "123 Main St",
    "address2": null,
    "city": "New York",
    "state": "NY",
    "zip": "10001",
    "country": "US",
    "customer_email": "john.doe@example.com",
    "customer_tel": "+1 555 0100",
    "note_seller": null,
    "is_paid": 0,
    "line_items": [
        {
            "product": {
                "name": "Unisex T-Shirt"
            },
            "quantity": 1
        }
    ],
    "shipment_order": null,
    "success": true,
    "message": "Seller Order Created Successfully."
}

Get Order

Retrieve details of a specific order by its internal ID.

GET /orders/{internal_order_id}

Example Request

GET https://api.vinaway.io/api/orders/VN7PIEA4FA5U

Response

{
    "internal_order_id": "VN7PIEA4FA5U",
    "status": 0,
    "amount_total": 2470,
    "customer_name": "John Doe",
    "line_items": [
        {
            "product": {
                "name": "Unisex T-Shirt"
            },
            "quantity": 1
        }
    ]
}

List Orders

Retrieve a paginated list of your orders.

GET /orders

Query Parameters

Parameter Type Description
page integer Page number (default: 1)
limit integer Number of items per page (default: 15)

Production Lines

Get a list of available production lines to use when creating an order.

GET /production-lines

Response

{
    "total": 2,
    "data": [
        {
            "id": 1,
            "name": "Standard",
            "description": "Inproduction: 1-3 days\nShip : 3-7days",
            "level": 1
        },
        {
            "id": 2,
            "name": "Express",
            "description": "Inproduction 4h\nShip 1-3 days",
            "level": 2
        }
    ]
}

Products

Get a list of all products.

GET /products

Query Parameters

Parameter Type Description
page integer Page number (default: 1)
limit integer Number of items per page (default: 100)

Response

{
    "total": 50,
    "data": [
        {
            "id": 1,
            "name": "Classic T-Shirt",
            "sku": "TSHIRT-001"
        }
    ]
}

Variants

Get a list of all product variants (SKUs). Use these IDs when creating orders.

GET /product-skus

Query Parameters

Parameter Type Description
page integer Page number (default: 1)
limit integer Number of items per page (default: 100)

Response

{
    "total": 120,
    "data": [
        {
            "id": 101,
            "sku": "TSHIRT-BLK-S",
            "product_name": "Classic T-Shirt",
            "color": "Black",
            "size": "S"
        }
    ]
}

Webhooks

Vinaway can send HTTP POST notifications to a URL you configure when certain events happen in your account. This allows your application to react in real-time without polling our API.

Event Description
order_processed Sent when an order finishes production and moves to "Waiting for Packaging" status.
order_status_updated Sent whenever an order's status changes. The payload includes both the previous and current status codes.
shipment_order_created Sent when a shipment order is created for an order. The payload includes the updated order with shipment details.

Configuration

Configure your webhook URL and secret via the API, or contact your Vinaway account manager. Once configured, Vinaway will begin sending POST requests to that URL for the events described below.

PATCH /sellers/webhook-config

Parameters

Field Type Required Description
webhook_url string (URL) No The URL Vinaway will send webhook requests to. Set to null to disable.
webhook_secret string No Shared secret used to sign webhook payloads via HMAC-SHA256.

Example Request

PATCH /sellers/webhook-config
Authorization: Bearer YOUR_TOKEN

{
    "webhook_url": "https://your-shop.com/webhooks/vinaway",
    "webhook_secret": "your_shared_secret_12345"
}

Response

{
    "success": true,
    "message": "Webhook configuration updated successfully",
    "data": {
        "id": 42,
        "name": "Example Store",
        "webhook_url": "https://your-shop.com/webhooks/vinaway",
        "webhook_secret": "your_shared_secret_12345"
    }
}

Request Format

Method: POST

Content-Type: application/json

All webhook payloads follow this structure:

{
    "event": "order_processed",
    "data": { ... }
}

Verifying Signatures

Each webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 hex digest of the request body. Verify it to ensure the webhook came from Vinaway:

$secret = "your_shared_secret";  // Provided by Vinaway for your account
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $body, $secret);
$received = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';

if (!hash_equals($expected, $received)) {
    http_response_code(401);
    exit;
}

Retry Policy

Vinaway expects a 2XX response within 10 seconds. If your endpoint returns a non-2XX status or times out, the webhook is NOT automatically retried. Please ensure your endpoint is reliable.

Webhook: Order Processed

Sent when an order finishes production and moves to "Waiting for Packaging" status. The payload contains the full order detail, identical to the GET /orders/{id} response.

Payload

{
    "event": "order_processed",
    "data": {
        "id": 313,
        "internal_order_id": "VN7PIEA4FA5U",
        "external_order_id": "ORD-2024-001",
        "type": 1,
        "status": 6,
        "is_paid": 1,
        "amount_subtotal": 2000,
        "amount_shipping": 470,
        "amount_total": 2470,
        "customer_name": "John Doe",
        "address1": "123 Main St",
        "city": "New York",
        "state_name": "NY",
        "country_name": "United States",
        "zip": "10001",
        "tracking_number": null,
        "tracking_carrier": null,
        "seller": {
            "id": 42,
            "name": "Example Store"
        },
        "seller_order_skus": [
            {
                "id": 501,
                "quantity": 1,
                "price": 2000,
                "product": {
                    "id": 1,
                    "name": "Unisex T-Shirt"
                },
                "seller_order_sku_designs": [...]
            }
        ],
        "production_line": {
            "id": 1,
            "name": "Standard"
        },
        "created_at": "2026-08-01 14:30:00"
    }
}

Order Status Reference

Status Code Name Description
-1Shipping Cost ProcessingOrder placed, calculating shipping
0PendingAwaiting processing
1Ordering DesignDesign being ordered
2Waiting for Design ConfirmationDesign awaiting seller confirmation
3Waiting for ProductionDesign confirmed, queued for production
4Approved for ProductionApproved by factory
5In ProductionCurrently being manufactured
6Waiting for PackagingWebhook trigger — production complete
7ShippedPackage handed to carrier
8CompletedDelivered / fulfillment complete
9RefundedOrder refunded
99CanceledOrder canceled

Webhook: Order Status Updated

Sent whenever an order transitions from one status to another. The payload contains the full order detail, plus the previous and current status codes so you can track exactly what changed.

Payload

{
    "event": "order_status_updated",
    "data": {
        "id": 313,
        "internal_order_id": "VN7PIEA4FA5U",
        "external_order_id": "ORD-2024-001",
        "status": 7,
        "previous_status": 6,
        "current_status": 7,
        "amount_total": 2470,
        "customer_name": "John Doe",
        "tracking_number": "TN123456789",
        "tracking_carrier": "DHL",
        "seller": {
            "id": 42,
            "name": "Example Store"
        },
        "seller_order_skus": [...],
        "shipment_order": { ... },
        "created_at": "2026-08-01 14:30:00"
    }
}

Special Fields

Field Type Description
previous_status integer The order status before the change.
current_status integer The new order status after the change.
status integer The current order status (same as current_status).

Webhook: Shipment Order Created

Sent when a shipment order is created for an order. The payload contains the full order detail, including the newly created shipment order information.

Payload

{
    "event": "shipment_order_created",
    "data": {
        "id": 313,
        "internal_order_id": "VN7PIEA4FA5U",
        "external_order_id": "ORD-2024-001",
        "status": 7,
        "amount_total": 2470,
        "customer_name": "John Doe",
        "tracking_number": "TN123456789",
        "tracking_carrier": "DHL",
        "seller": {
            "id": 42,
            "name": "Example Store"
        },
        "seller_order_skus": [...],
        "shipment_order": {
            "id": 101,
            "shipment_order_code": "SO-2026-001",
            "tracking_number": "TN123456789",
            "tracking_carrier": "DHL",
            "total_weight": 0.5,
            "fee": 15000,
            "status": "pending"
        },
        "created_at": "2026-08-01 14:30:00"
    }
}