GraphQL Overview
The GraphQL API provides a typed alternative to the REST API.
GraphQL is a data query and manipulation language that allows specifying what data is to be retrieved ("declarative data fetching") or modified.
It is available at:
- Authentication: add
Authorization: Bearer <token>header for all data operations - Introspection: allowed without authentication (schema fetch only)
Headers
All secured operations require the Authorization header:
{
"Authorization": "Bearer YOUR_ACCESS_TOKEN"
}
Take a look at the authentication guide for details on obtaining an access token.
Quick start (cURL)
curl -X POST https://api.axro.com/gql/v1 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"query": "query { products(page:1, limit:5) { totalPages products { productNumber brand stock } } }"
}'
Queries
products
List products with filtering and pagination.
All arguments are optional.
| Name | Type | Required | Description |
|---|---|---|---|
format | string | ❌ | Response format: 'json' (default) or 'xml' (BMEcat 2005 format) |
product_number | string | ❌ | Filter by single or comma-separated AXRO product numbers (e.g., 'CANL055BK' or 'CANL055BK,CANL056WH') |
oem | string | ❌ | Filter by single or comma-separated OEM numbers (e.g., '3016C002' or '3016C002,CF540A') |
ean | string | ❌ | Filter by single or comma-separated EAN numbers (e.g., '4549292124699' or '4549292124699,4549292124706') |
brand | string | ❌ | Filter by single or comma-separated brand names (e.g., 'HP,Canon,Epson') |
category | string | ❌ | Filter by single or comma-separated category IDs (e.g., '50593,50638') |
page | string | ❌ | Page number for pagination (default: 1) |
limit | string | ❌ | Number of items per page (default: 100) |
Example Request
- GraphQL
query {
products(page: 1, limit: 10, brand: "HP") {
totalPages
products {
productNumber
ean
brand
stock
price { fromQuantity toQuantity price }
title { enGb deDe }
category { id en de }
categories { id en de }
attributes { id name attributes { id title value } }
modifiedAt
}
}
}
Example Response
{
"data": {
"products": {
"totalPages": 120,
"products": [
{
"productNumber": "CANT7260C",
"brand": "Canon",
"oemNumber": "6944B002",
"stock": 0,
"price": [],
"title": {
"enGb": "Canon Toner C-EXV45 / 6944B002 Cyan (6944B002/6944B002AA)",
"deDe": "Canon Toner C-EXV45 / 6944B002 Cyan (6944B002/6944B002AA)"
},
"category": {
"id": 51158,
"de": "Kopiertoner",
"en": "Copy toner"
},
"categories": [
{
"id": 51158,
"de": "Kopiertoner",
"en": "Copy toner"
},
{
"id": 23,
"de": "Tinten & Toner",
"en": "Inks & Toner"
}
],
"attributes": [
{
"id": 37,
"name": "Packaging Data",
"attributes": [
{
"id": 519,
"title": "Type of packaging",
"value": "Box"
}
]
},
{
"id": 35,
"name": "Weight and Dimensions",
"attributes": [
{
"id": 203,
"title": "Weight",
"value": "4.5 kg"
},
{
"id": 225,
"title": "Depth",
"value": "430 mm"
}
]
}
],
"modifiedAt": "2025-09-29 20:46:01+00:00"
}
]
}
}
}
IMPORTANT Deprecation notice: Field category in the response will be removed in future versions. Use categories instead! It holds the same categories, and category is simply the first entry of that list.
Product attributes
attributes mirrors the REST products endpoint: every entry is an attribute group
(id, name) holding its own attributes (id, title, value). Groups are sorted
by name, attributes by id. Values are always strings, also for numeric data, and a
product without technical data returns an empty list.
productStocks
Bulk stock lookup for many products at once.
- Input:
items(max 5000) where each element contains exactly one identifier:productNumbereanoemfsku
- You can mix identifier types in the same request.
- Output is returned in the same order as input.
- Per-row failures are returned via
error(other rows still succeed).
Example Request
- GraphQL
query {
productStocks(items: [
{ productNumber: "CANL055BK" }
{ ean: "4549292124699" }
{ oem: "3016C002" }
{ fsku: "FSKU-999" }
]) {
product
stock
error
}
}
Example Response
{
"data": {
"productStocks": [
{ "product": "CANL055BK", "stock": 42, "error": null },
{ "product": "4549292124699", "stock": 10, "error": null },
{ "product": "3016C002", "stock": 7, "error": null },
{ "product": "FSKU-999", "stock": 0, "error": "fsku_not_found" }
]
}
}
Error codes:
not_foundfsku_not_found
categories
List all available categories.
Example Request
- GraphQL
query {
categories {
id
de
en
}
}
Example Response
{
"data": {
"categories": [
{
"id": 83104,
"de": "SD-Karten",
"en": "SD cards"
},
{
"id": 83170,
"de": "Autorennbahnen",
"en": "Car racetracks"
}
]
}
}
brands
List available brands for the current user (after applying visibility rules).
Example Request
- GraphQL
query {
brands {
brands
}
}
Example Response
{
"data": {
"brands": {
"brands": [
"Acer",
"IBM",
"Utax"
]
}
}
}
fskuMappings
List fSKU → product number mappings for the current user.
Arguments (all optional):
| Name | Type | Required | Description |
|---|---|---|---|
page | Int | ❌ | Page number for pagination (default: 1) |
limit | Int | ❌ | Number of items per page (default: 10000, max: 50000) |
q | String | ❌ | Optional substring filter applied to fsku or productNumber |
Example Request
- GraphQL
query {
fskuMappings(page: 1, limit: 100, q: "AXRO") {
mappings {
fsku
productNumber
}
page
limit
total
totalPages
}
}
Example Response
{
"data": {
"fskuMappings": {
"mappings": [
{ "fsku": "FSKU-999", "productNumber": "AXRO123" }
],
"page": 1,
"limit": 100,
"total": 1,
"totalPages": 1
}
}
}
userInfo
Basic info about the current user.
Example Request
- GraphQL
query {
userInfo {
email
customer {
company
}
billingAddress {
company
street
zip
city
country
}
}
}
Example Response
{
"data": {
"userInfo": {
"email": "user@example.com",
"customer": {
"company": "Example Corp"
},
"billingAddress": {
"company": "Example Corp",
"department": "Purchasing",
"street": "123 Example St",
"zip": "10001",
"city": "New York",
"country": "US"
}
}
}
}
billingAddress
Retrieve the billing address for the current user.
Example Request
- GraphQL
query {
billingAddress {
company
department
street
zip
city
country
}
}
Example Response
{
"data": {
"billingAddress": {
"company": "Example Corp",
"department": "Accounting",
"street": "456 Bill St",
"zip": "10002",
"city": "New York",
"country": "US"
}
}
}
shippingAddresses
List shipping addresses for the current user.
Example Request
- GraphQL
query {
shippingAddresses {
id
company
department
street
zip
city
country
phone
email
status
info
}
}
Example Response
{
"data": {
"shippingAddresses": [
{
"id": "7284adc6-db5f-55c1-9511-4d12b3a356f1",
"company": "Example Corp",
"department": "Logistics",
"street": "123 Shipping Ln",
"zip": "10001",
"city": "New York",
"country": "US",
"email": "logistics@example.com",
"phone": "+15551234",
"status": "WAITING_APPROVAL",
"info": "Please wait for approval."
}
]
}
}
orderList
List orders for the current customer (via information service).
Arguments (all optional):
| Name | Type | Required | Description |
|---|---|---|---|
page | Int | ❌ | Page number (default: 1) |
commission | String | ❌ | Filter orders by commission |
Response includes:
- orders: [OrderItem]
- totalPages: Int
- error: String (nullable) — present on 400 responses; other errors appear as top-level GraphQL errors
Example Request
- GraphQL
query {
orderList(page: 1, commission: "BR1234") {
totalPages
orders {
orderNumber
date
commission
currency
orderTotal
orderSource
}
}
}
Example Response
{
"data": {
"orderList": {
"orders": [
{
"orderNumber": "522214",
"date": "2025-08-19",
"commission": "25310133",
"currency": "EUR",
"orderTotal": 247326,
"orderSource": "Webshop"
}
],
"totalPages": 1,
"error": null
}
}
}
orderDetails
Retrieve order details by order number.
Response includes:
- orderNumber: String
- order: OrderDetailMessage
- error: String (nullable) — present on 400 responses; other errors appear as top-level GraphQL errors
Example Request
- GraphQL
query {
orderDetails(orderNumber: "1234567") {
orderNumber
order {
invoiceNumber
date
commission
currency
orderTotal
orderSource
carrier
shippingAddress {
company
street
zip
city
}
billingAddress {
company
street
zip
city
}
items {
productNumber
orderNumber
oemNumber
quantity
total
},
"error": null
}
}
}
Example Response
{
"data": {
"orderDetails": {
"orderNumber": "123456",
"order": {
"invoiceNumber": "654321",
"date": "2025-08-19",
"commission": "25310133",
"currency": "EUR",
"orderTotal": 3080,
"orderSource": "online",
"shippingAddress": {
"company": "AXRO GmbH",
"street": "Schnackenburgallee 183-201",
"zip": "22525",
"city": "Hamburg"
},
"billingAddress": {
"company": "AXRO GmbH",
"street": "Schnackenburgallee 183-201",
"zip": "22525",
"city": "Hamburg"
},
"items": [
{
"productNumber": "EPSET20692",
"orderNumber": "123456",
"oemNumber": "c13s020692",
"quantity": 1,
"total": 2785
},
{
"productNumber": "FR_AUTO_MD",
"orderNumber": "123456",
"oemNumber": "FR_AUTO_MD",
"quantity": 1,
"total": 295
}
]
}
}
}
}
shipmentList
List shipments (tolerant to missing tracking data; empty strings if not available).
Arguments (all optional):
| Name | Type | Required | Description |
|---|---|---|---|
page | Int | ❌ | Page number for pagination (default: 1) |
orderNumber | String | ❌ | Filter shipments by a specific order number |
commission | String | ❌ | Filter shipments by commission |
Response includes:
- shipments: [ShipmentItem]
- totalPages: Int
- error: String (nullable) — present on 400 responses; other errors appear as top-level GraphQL errors
- GraphQL
Example Request
query {
shipmentList(page: 1, orderNumber: "123456", commission: "BR1234") {
totalPages
shipments {
shipmentNumber
company
commission
status
date
shippingDate
trackingUrl
trackingCode
carrier
}
}
}
Example Response
{
"data": {
"shipmentList": {
"shipments": [
{
"shipmentNumber": "123456",
"company": "AXRO GmbH",
"commission": "25310133",
"status": "OnTheWay",
"date": "20.08.2025",
"shippingDate": "19.08.2025",
"trackingUrl": "https://www.ups.com/track?loc=en_GB&tracknum=1234567890",
"trackingCode": "1234567890",
"carrier": "UPS"
}
],
"totalPages": 1,
"error": null
}
}
}
shipmentDetails
Retrieve shipment details by shipment number.
Response includes:
- shipmentNumber: String
- shipment: ShipmentDetailMessage
- error: String (nullable) — present on 400 responses; other errors appear as top-level GraphQL errors
Example Request
- GraphQL
query {
shipmentDetails(shipmentNumber: "654321") {
shipmentNumber
shipment {
orderNumbers
invoiceNumber
shipmentNumber
shippingDate
items {
productNumber
orderNumber
oemNumber
commission
quantity
total
}
}
}
}
Example Response
{
"data": {
"shipmentDetails": {
"shipmentNumber": "654321",
"shipment": {
"orderNumbers": [
"111111"
],
"invoiceNumber": "123456",
"shipmentNumber": "654321",
"shippingDate": "2025-08-19",
"items": [
{
"productNumber": "EPSET20692",
"orderNumber": "111111",
"oemNumber": "c13s020692",
"commission": "25310133",
"quantity": 1,
"total": 2785
},
{
"productNumber": "FR_AUTO_MD",
"orderNumber": "111111",
"oemNumber": "FR_AUTO_MD",
"commission": "25310133",
"quantity": 1,
"total": 295
}
]
},
"error": null
}
}
}
trackingHistory
Retrieve tracking history by shipment number. The response includes:
- shipmentNumber: String
- history: JSON (preserves dynamic keys like tracking codes and state indices)
- error: String (nullable) — present if the service rejects the request or an error occurs
Example Request
- GraphQL
query {
trackingHistory(shipmentNumber: "567517") {
shipmentNumber
history
}
}
Example Response (success)
{
"data": {
"trackingHistory": {
"shipmentNumber": "123456",
"history": {
"00340434111111199160": {
"states": {
"0": {
"time": "2025-08-18T13:34:00+02:00",
"event": "Delivered successfully",
"phase": "Delivery",
"location": { "place": "" },
"timezone": "Etc/GMT-2",
"event_key": "H10",
"phase_key": "H",
"carrier_name": "DHL",
"additional_info": []
}
},
"estimatedDeliveryDate": {
"date": "2025-08-18 14:35:00.000000",
"timezone_type": 3,
"timezone": "Europe/Berlin"
},
"delivered": true
}
},
"error": null
}
}
}
Example Response (error)
{
"data": {
"trackingHistory": {
"shipmentNumber": "123456",
"history": {},
"error": "shipmentNumber does not belong to customerNumber"
}
}
}
Mutations
shippingCreate
Create a shipping address or validate without saving.
Arguments:
input: { company, department, firstname?, lastname?, street, zip, city, country, phone?, email? }check: Boolean = false— if true, validates/normalizes without saving (no id in response)
Returns:
- On success: suggestion (check=true) or created ShippingAddressInfo
- On error:
{ error: true, status: Int, body: JSON }from the REST layer
Note: this mutation forwards to POST /api/v1/address/shipping/, so phone numbers follow the same normalization rules. Common notations such as 0170 1234567 are rewritten to +491701234567 using country, and a number that does not exist in the numbering plan of its own dialling code is rejected with status 422 in body, with a message naming that country and an example. The address country only decides how a national number without + or 00 is read. The stored value is the normalized one.
| Name | Type | Required | Description |
|---|---|---|---|
company | string | ✅ | Company name (max 35 chars) |
department | string | ✅ | Department name (max 35 chars) |
firstname | string | ❌ | Contact first name |
lastname | string | ❌ | Contact last name |
street | string | ✅ | Street and number (max 35 chars) |
zip | string | ✅ | ZIP/Postal code |
city | string | ✅ | City (max 35 chars) |
country | string | ✅ | Country code (ISO 3166-1 alpha-2) |
phone | string | ❌ | Phone number, normalized to E.164 against country |
email | string | ❌ | Email address |
Example Request (check=false)
- GraphQL
mutation createShipping {
shippingCreate(
input: {
company: "Example Corp
firstname: "John"
lastname: "Doe"
department: "Warehouse"
street: "123 Shipping St"
zip: "10001"
city: "New York"
country: "US"
phone: "+4940123456"
email: "test@example.com"
}
check: false
)
}
Example Response
{
"data": {
"shippingCreate": {
"id": "95867100-43d3-5416-8729-74722012aef1",
"company": "Example Corp",
"department": "Warehouse",
"firstname": "John",
"lastname": "Doe",
"street": "123 Shipping St",
"zip": "10001",
"city": "New York",
"country": "US",
"phone": "+4940123456",
"email": "test@example.com",
"status": "WAITING_APPROVAL",
"info": "Please wait for approval."
}
}
}
Example Request (check=true)
- GraphQL
mutation createShipping {
shippingCreate(
input: {
company: "Example Corp"
department: "Warehouse"
street: "Ballindamm 40"
zip: ""
city: ""
country: "DE"
}
check: true
)
}
Example Response
{
"data": {
"shippingCreate": {
"company": "Example Corp",
"department": "Warehouse",
"street": "Ballindamm 40",
"zip": "20095",
"city": "Hamburg",
"country": "DE",
"phone": null,
"email": null,
"status": "CHECK_ONLY",
"info": "Suggested validated/normalized address. Not saved."
}
}
}
shippingUpdate
Update a shipping address by ID (follows same permission rules as REST).
Arguments:
id: String!input: { phone?, email? }
The number is normalized against the country stored on the address, so a national number such as 0170 1234567 is accepted without sending a country.
Note: the GraphQL layer forwards only fields that are not null, so phone: null leaves the stored number unchanged. Send an empty string (phone: "") to remove it. The REST endpoint accepts both.
Example Request
- GraphQL
mutation updateShipping {
shippingUpdate(
id: "95867100-43d3-5416-8729-74722012aef1"
input: {
phone: "+4940123456",
email: "test@example.com"
}
)
}
Example Response
{
"data": {
"shippingUpdate": {
"id": "95867100-43d3-5416-8729-74722012aef1",
"company": "Example Corp",
"department": "Warehouse",
"firstname": "John",
"lastname": "Doe",
"street": "123 Shipping St",
"zip": "10001",
"city": "New York",
"country": "US",
"phone": "+4940123456",
"email": "test@example.com",
"status": "USABLE",
"info": "Can be used for shipping."
}
}
}
orderCreate
Create/prepare an order, optionally placing it immediately.
Arguments:
order: { shippingAddressId: String!, cart: [{ productNumber?: String, fsku?: String, quantity: Int! }]!, customReference?, additionalInformation? }place: Boolean = false— if true, places the order with?place=1
Notes:
- Each cart item must include either
productNumberorfsku. - If both are provided,
productNumberwins.
Example Request
- GraphQL
mutation createOrder {
orderCreate(
order: {
shippingAddressId: "6f0c76f6-5af3-4a47-9a58-6e3f0a361234"
cart: [
{ productNumber: "CANL055BK", quantity: 2 },
{ fsku: "FSKU-999", quantity: 1 }
]
customReference: "PO-1234"
additionalInformation: "Leave at front desk"
}
place: true
)
}
Example Response
{
"data": {
"orderCreate": {
"shipping_address": {
"id": "ff81b118-1d53-5ebf-b99e-063c60ce9c2e",
"company": "Acme Inc.",
"department": "Office",
"firstname": "John",
"lastname": "Doe",
"street": "123 Main St",
"zip": "10001",
"city": "New York",
"country": "US",
"email": "test@example.com",
"phone": "+15551234"
},
"billing_address": {
"company": "Acme Inc.",
"department": "Accounting",
"street": "123 Main St",
"zip": "10001",
"city": "New York",
"country": "US"
},
"cart": [
{
"product_number": "CANL055BK",
"quantity": 2,
"difference": 0,
"unit_price": 1000,
"uhg_unit": 1200,
"uhg_total": 1200,
"sub_total": 2200
},
{
"product_number": "HP303A",
"quantity": 1,
"difference": 0,
"unit_price": 1000,
"uhg_unit": 1200,
"uhg_total": 1200,
"sub_total": 2200
}
],
"toll": 295,
"freight_costs": 490,
"grand_total": 2985,
"custom_reference": "PO-1234",
"additional_information": "Leave at front desk",
"order_placed": true,
"place_order_url": "Order placed"
}
}
}
Tips
- Introspection is allowed without a token, but running real queries and mutations requires
Authorization: Bearer <token>. - Field names in GraphQL use
camelCase(e.g.,productNumber,totalPages,enGb,deDe).