Lumina Print API · v1 Documentation Support

Lumina Print API Documentation

The Lumina Print API v1 is an API service for viewing the product catalog, getting order details, and completing orders for our printing and fulfillment services. Requests are made using standard GET and POST. All responses are in JSON format.

Overview

Base URL examples:

URL: https://api.luminaprint.io/v1

Supported Endpoints

MethodEndpointPurpose
POST/auth/loginGet access token.
GET/catalog/productsList catalog products with available stock.
POST/orders/createCreate a new order.
GET/orders/myList your own orders.
GET/orders/my/{order_code_or_ref_id}Get order detail by order code or reference id.
POST/orders/{order_code}/cancelCancel an eligible order.
POST/webhooksCreate webhook subscription.
GET/webhooksList webhook subscriptions.
GET/webhooks/{webhook_id}Get webhook subscription.
PATCH/webhooks/{webhook_id}Update webhook subscription.
DELETE/webhooks/{webhook_id}Delete webhook subscription.
POST/webhooks/{webhook_id}/testSend a test delivery.
GET/webhook-deliveriesList webhook delivery attempts.

Authentication Header

Every endpoint except /auth/login requires a Bearer token.

Authorization: Bearer <access_token>
Content-Type: application/json

Auth

POST/auth/login

Authenticates a user and returns an access token. Use the returned token in the Authorization header for all other requests.

Body Parameters

FieldTypeRequiredDescription
usernamestringYesUsername
passwordstringYesPassword

Request Example

{
  "username": "clientTest",
  "password": "your-password"
}

Response Example

{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 1800
}

Rate Limits

Rate limits protect the API from accidental spikes and repeated retries. Build integrations with retry backoff and avoid sending the same request in tight loops.

Current V1 limit: public client API traffic is shaped with a token bucket — 15 requests per second sustained, 150 request burst capacity. Login is handled separately so authentication remains available during normal client API throttling.

The bucket holds up to 150 tokens and refills at 15 tokens per second. A short burst of up to 150 requests is accepted instantly; sustained traffic above 15 RPS gets 429 responses once the bucket empties.

ScopeSustainedBurstNotes
/orders/** 15 RPS 150 requests Applies to create, cancel, list, and detail order endpoints. Repeated order creation should use a unique reference_id per order.
/catalog/**, /webhooks/**, /webhook-deliveries 15 RPS 150 requests Applies to public catalog and webhook management endpoints. Keep polling intervals reasonable. Use webhooks for order status changes instead of frequent polling.

When a Limit Is Exceeded

The API returns 429 Too Many Requests. Wait before retrying. Use exponential backoff with jitter, for example 1s, 2s, 4s, then cap retries.

{
  "code": "rate-limit.exceeded",
  "message": "Too many requests. Please retry after a short delay.",
  "timestamp": "2026-05-25T20:15:30Z"
}

Recommended Client Behavior

  • Retry 429 responses with exponential backoff and jitter.
  • Do not retry validation errors such as 400 or 422 without changing the request.
  • For bulk order import, queue requests on your side and send them steadily instead of firing every order at once.
  • Use webhooks for order status changes instead of polling order detail repeatedly.

Catalog

GET/catalog/products?page=0&size=20

Lists catalog products. Each product includes available_stock. Use the returned sku_code when creating orders.

Query Parameters

ParameterTypeRequiredDescription
pageintegerNoZero-based page number. Default is 0. Negative values are clamped to 0.
sizeintegerNoNumber of products per page. Default 20. Maximum 1000 — values above the cap are silently clamped, values ≤ 0 collapse to the default. The catalog endpoint is exempt from the usual 100-row cap so storefronts can pull the full assigned product set in one request.
searchstringNoSearch by product name, SKU, color, size, or other visible catalog text.

Response Fields

FieldDescription
content[].sku_codeCatalog SKU to send in order_items[].sku.
content[].reference_sku_codeYour specific SKU, if one was configured by Lumina Print. May be null.
content[].brandProduct brand, if available.
content[].modelProduct model or product line name, if available.
content[].colorProduct color.
content[].sizeProduct size.
content[].available_stockAvailable stock quantity currently known by Lumina Print.

Response Example

{
  "content": [
    {
      "sku_code": "101085001200134",
      "reference_sku_code": "CLIENT-SKU-BLACK-L",
      "brand": "Gildan",
      "model": "5000",
      "color": "Black",
      "size": "L",
      "available_stock": 42
    }
  ],
  "page": 0,
  "size": 20,
  "total_elements": 1,
  "total_pages": 1
}

Orders

POST/orders/create

Creates a new print-on-demand order.

The response returns order_code. Store this value for future tracking and cancellation.

Request Body

See the full field-by-field schema in Create Order Body.

Response Example

{
  "order_code": "ORD-RBYSTKKRB27Q",
  "reference_id": "client-order-10001",
  "status": "APPROVED",
  "created_at": "2026-05-25T20:15:30Z"
}
GET/orders/my?page=0&size=20&status=APPROVED

Lists orders belonging to the authenticated client.

Query Parameters

ParameterTypeRequiredDescription
pageintegerNoZero-based page number. Default is 0.
sizeintegerNoNumber of orders per page. Recommended range: 10 to 100.
statusstringNoFilter by status: APPROVED, IN_PRODUCTION, SHIPPED, or CANCELLED.
searchstringNoSearch by order_code or reference_id.

Response Example

{
  "content": [
    {
      "order_code": "ORD-RBYSTKKRB27Q",
      "reference_id": "client-order-10001",
      "status": "IN_PRODUCTION",
      "created_at": "2026-05-25T20:15:30Z"
    }
  ],
  "page": 0,
  "size": 20,
  "total_elements": 1,
  "total_pages": 1
}
GET/orders/my/{order_code_or_ref_id}

Returns one order owned by the authenticated client. The path value can be either Lumina's order_code or your own reference_id.

Path Parameters

ParameterTypeRequiredDescription
order_code_or_ref_idstringYesUse ORD-... returned by create order, or your original reference_id.

Response Example

{
  "order_code": "ORD-RBYSTKKRB27Q",
  "reference_id": "client-order-10001",
  "status": "IN_PRODUCTION",
  "recipient": {
    "name": "Jane Customer",
    "city": "Austin",
    "state": "TX",
    "country": "US",
    "zip": "78701"
  },
  "order_items": [
    {
      "sku": "101085001200134",
      "quantity": 1,
      "name": "Black Large Shirt",
      "placements": [
        {
          "placement": "front",
          "technique": "DTG"
        }
      ]
    }
  ],
  "created_at": "2026-05-25T20:15:30Z",
  "updated_at": "2026-05-25T20:20:12Z"
}
POST/orders/{order_code}/cancel

Requests cancellation for an eligible order. Lumina Print first asks the production provider to cancel. If the provider does not confirm cancellation, Lumina Print will not cancel the local order.

Path Parameters

ParameterTypeRequiredDescription
order_codestringYesLumina order code returned by /orders/create.

Body Parameters

FieldTypeRequiredDescription
reasonstringYesShort reason for cancellation, such as duplicate order or customer request.

Request Example

{
  "reason": "Customer requested cancellation"
}

Response Fields

FieldTypeDescription
order_codestringLumina order code (echoed from the path parameter).
reference_idstringThe reference_id the client supplied at order creation.
statusstringPublic order status projection. On a successful cancel this is cancelled.
can_cancelbooleanWhether another cancel attempt would succeed. Always false on a successful cancel response — the order is now terminal.
why_blockedstringOptional. Partner-safe reason if the order is in a blocked or failed state. Omitted from the JSON when not applicable.

Response Example

{
  "order_code": "ORD-RBYSTKKRB27Q",
  "reference_id": "client-order-10001",
  "status": "cancelled",
  "can_cancel": false
}

Create Order Body

This is the body for POST /orders/create. DTG and DTF order placement only.

Top-Level Fields

FieldTypeRequiredDescription
reference_idstringNoYour unique order identifier. Use a stable value so duplicate submissions can be detected. Allowed characters: alphanumerics, dashes, and underscores.
shipping_urlstringNoShipping label url.
recipientobjectYesRecipient name, address, email, and phone.
order_itemsarrayYesOne or more products to print and ship.

recipient

FieldTypeRequiredDescription
namestringYesFull recipient name.
companystringNoCompany name, if shipping to a business.
street1stringYesStreet address line 1.
street2stringNoApartment, suite, unit, floor, or other secondary address detail.
citystringYesCity.
statestringYesState, province, or region. Use common region codes where applicable, such as TX.
countrystringYesTwo-letter ISO country code, such as US, CA, or GB.
zipstringYesPostal or ZIP code.
emailstringNoRecipient email. Recommended for shipment communication.
phonestringNoRecipient phone number. Recommended for carrier delivery issues. Must be in E.164 format with country code (e.g. +17531378536) when supplied.
taxnumberstringConditionallyTax identifier when required by destination country.

order_items[]

FieldTypeRequiredDescription
skustringYesCatalog sku_code returned by /catalog/products.
quantityintegerYesNumber of units for this line item. Must be greater than 0.
placementsarrayYesPrint placements for this product, such as front or back.

order_items[].placements[]

FieldTypeRequiredDescription
placementstringYesPrint location. Common values: front, back, left_sleeve, right_sleeve.
techniquestringYesPrint technique. DTG and DTF only.
print_area_typestringNoDefaults to simple.
layersarrayYesDesign files or text layers to print on this placement.

order_items[].placements[].layers[]

FieldTypeRequiredDescription
typestringYesLayer type. Use default file.
urlstringYesPublicly reachable HTTPS URL for the artwork file.
mockup_urlstringYesPublicly reachable HTTPS URL for the mockup/preview image.
width number No Optional. Print width in inches (1–14). If provided, height must also be provided.
height number No Optional. Print height in inches (1–16). If provided, width must also be provided.

Request Example

{
  "reference_id": "client-order-10001",
  "shipping_url": "https://cdn.example.com/shipping/shipping-label.pdf",
  "recipient": {
    "name": "Jane Customer",
    "company": "Jane's Store",
    "street1": "100 Congress Ave",
    "street2": "Suite 200",
    "city": "Austin",
    "state": "TX",
    "country": "US",
    "zip": "78701",
    "email": "jane@example.com",
    "phone": "+15125550100"
  },
  "order_items": [
    {
      "sku": "123456",
      "quantity": 1,
      "placements": [
        {
          "placement": "front",
          "technique": "DTG",
          "print_area_type": "simple",
          "layers": [
            {
              "type": "file",
              "url": "https://cdn.example.com/artwork/front.png",
              "mockup_url": "https://cdn.example.com/mockup/front.png",
              "width": 10,
              "height": 12
            }
          ]
        },
        {
          "placement": "back",
          "technique": "DTF",
          "print_area_type": "simple",
          "layers": [
            {
              "type": "file",
              "url": "https://cdn.example.com/artwork/back.png",
              "mockup_url": "https://cdn.example.com/mockup/back.png"
            }
          ]
        }
      ]
    }
  ]
}

Client-Visible Statuses

Client APIs expose a small, stable status set. Internal workflow statuses are not part of this public contract.

StatusMeaning
APPROVEDOrder was accepted and is waiting to enter production.
IN_PRODUCTIONOrder is being processed or produced.
SHIPPEDOrder has shipped or has carrier tracking activity.
CANCELLEDOrder was cancelled.

Webhooks

Webhooks notify your system when important order events happen. Manage subscriptions through the API. Webhook management is not handled in the client portal.

Supported event types: order.created, order.status_updated.
POST/webhooks

Creates a webhook subscription for the authenticated client. The secret is returned only once on creation; store it securely.

Body Parameters

FieldTypeRequiredDescription
endpoint_urlstringYesHTTPS URL that will receive webhook POST requests. Production URLs must not point to localhost or private network addresses.
event_typesarray of stringsYesEvents to send to this endpoint. Allowed values: order.created, order.status_updated.

Request Example

{
  "endpoint_url": "https://your-system.example.com/lumina/webhooks",
  "event_types": ["order.created", "order.status_updated"]
}

Response Example

{
  "id": "7e56d82d-2112-4f98-b6f8-6e6fa5c4b313",
  "endpoint_url": "https://your-system.example.com/lumina/webhooks",
  "event_types": ["order.created", "order.status_updated"],
  "active": true,
  "secret": "whsec_...",
  "created_at": "2026-05-25T20:15:30Z",
  "updated_at": "2026-05-25T20:15:30Z",
  "message": "Store the secret now — it is only returned on creation and rotate-secret."
}
GET/webhooks

Lists all webhook subscriptions owned by the authenticated client. The response is a flat JSON array — there is no pagination wrapper. Subscription counts per client are bounded by tenant policy, so the full list is returned in one response.

Response Example

[
  {
    "id": "7e56d82d-2112-4f98-b6f8-6e6fa5c4b313",
    "endpoint_url": "https://your-system.example.com/lumina/webhooks",
    "event_types": ["order.created", "order.status_updated"],
    "active": true,
    "created_at": "2026-05-25T20:15:30Z",
    "updated_at": "2026-05-25T20:15:30Z"
  }
]
GET/webhooks/{webhook_id}

Returns one webhook subscription owned by the authenticated client.

Path Parameters

ParameterTypeRequiredDescription
webhook_idUUIDYesWebhook subscription id returned by POST /webhooks.
PATCH/webhooks/{webhook_id}

Updates a webhook subscription. Send only fields that should change.

Path Parameters

ParameterTypeRequiredDescription
webhook_idUUIDYesWebhook subscription id.

Body Parameters

FieldTypeRequiredDescription
endpoint_urlstringNoNew HTTPS destination URL.
event_typesarray of stringsNoReplacement event list. Allowed values: order.created, order.status_updated.
activebooleanNoSet false to pause deliveries without deleting the subscription.

Request Example

{
  "active": false
}
DELETE/webhooks/{webhook_id}

Deletes a webhook subscription. Future matching events will no longer be delivered to this endpoint.

Path Parameters

ParameterTypeRequiredDescription
webhook_idUUIDYesWebhook subscription id.
POST/webhooks/{webhook_id}/test

Sends a test webhook to the subscription URL. Test deliveries are for connectivity verification and should not create or update real orders in your system.

Path Parameters

ParameterTypeRequiredDescription
webhook_idUUIDYesWebhook subscription id to test.

Response Example

{
  "delivered": true,
  "status_code": 200,
  "message": "Test webhook delivered"
}

Webhook Signature

Every webhook delivery includes HMAC signature headers. Verify the signature before trusting the payload.

HeaderDescription
X-Lumina-Event-IdUnique event id. Use this for deduplication.
X-Lumina-Event-TypeEvent type, such as order.created.
X-Lumina-TimestampISO-8601 UTC timestamp used in the signature payload (for example 2026-05-25T20:20:00Z). Pass this exact header value into the HMAC computation — do not re-format or convert to epoch.
X-Lumina-SignatureHMAC-SHA256 signature of {timestamp}.{raw_body} using your webhook secret.

Webhook Deliveries

GET/webhook-deliveries?subscription_id={subscription_id}&page=0&size=20

Lists webhook delivery attempts for the authenticated client. Use this endpoint to debug failed or retried webhook deliveries.

Query Parameters

ParameterTypeRequiredDescription
subscription_idUUIDNoFilter attempts for one webhook subscription. Cross-tenant ids surface as an empty result, not 403.
event_typestringNoFilter by event type, such as order.created or order.status_updated.
statusstringNoFilter by delivery status. Allowed values: PENDING, DELIVERING, SUCCEEDED, FAILED, RETRYING, EXHAUSTED, CANCELLED.
pageintegerNoZero-based page number. Default 0. Must be >= 0 — out of range responds 400.
sizeintegerNoPage size. Default 20, allowed range 1..100 — out of range responds 400.

Response Example

{
  "content": [
    {
      "id": "d63156a3-6a09-4fe6-bbe9-88c427a1e5ed",
      "subscription_id": "7e56d82d-2112-4f98-b6f8-6e6fa5c4b313",
      "event_id": "evt_01HY...",
      "event_type": "order.status_updated",
      "status": "SUCCEEDED",
      "http_status": 200,
      "attempt_count": 1,
      "next_retry_at": null,
      "last_error": null,
      "created_at": "2026-05-25T20:20:00Z",
      "completed_at": "2026-05-25T20:20:01Z"
    }
  ],
  "page": 0,
  "size": 20,
  "total_elements": 1,
  "total_pages": 1
}

Field notes:

  • http_status — HTTP response status from your endpoint on the last attempt. null until the first dispatch is attempted.
  • next_retry_at — present only while the row is in RETRYING. Cleared on terminal status.
  • last_error — last failure detail (connection error, non-2xx body excerpt). Useful for diagnosing your endpoint without enabling delivery payload logging.
  • completed_at — set when the row reaches a terminal status (SUCCEEDED, FAILED, EXHAUSTED, CANCELLED).

Errors

Errors use a consistent JSON shape. Some validation errors may include field-level details.

{
  "code": "order.not-found",
  "message": "Order was not found.",
  "timestamp": "2026-05-25T20:15:30Z"
}
HTTP StatusMeaningTypical Cause
400Bad requestMalformed JSON, missing required field, invalid enum value, or invalid file URL.
401UnauthorizedMissing, expired, or invalid token.
403ForbiddenToken is valid but not allowed to use the requested resource.
404Not foundOrder, product, webhook, or delivery does not exist for this client.
409ConflictDuplicate referance id, order cannot be cancelled
429Too many requestsRate limit exceeded. Retry later with exponential backoff.
422Validation failedField value is syntactically valid but not acceptable for processing.
503Service unavailableService is temporarily unavailable.