Pixel Shipping
PricingImplementationPolicyTermsContactsLog in

Pixel Shipping

Company legal name (TODO)

All rights reserved.

Product

  • Home
  • Pricing
  • Implementation

Legal

  • Policy
  • Terms

Contact

  • Contacts

On this page

  • Connect
  • Quickstart
  • Catalog
    • catalog
    • recommendSize
    • shippingOptions
  • Labels
    • createDraftLabel
    • purchaseLabel
    • createLabel
    • createReturnLabel
    • labels
    • label
    • trackLabel
    • downloadLabelPdf
    • cancelLabel
  • Stations
    • searchStations
  • Webhooks
    • registerWebhookEndpoint
    • webhookEndpoints
  • Usage
    • ownUsage
  • Errors

Implementation

Connect over GraphQL or the generated TypeScript SDK. There are no Shopify, WooCommerce, Magento, or other shop plugins. This page covers every public operation with copy-paste examples.

Connect

Send POST requests to the public GraphQL endpoint with an organization API key. Create a test or live key in the backoffice after you sign up.

Endpoint

POST http://localhost:4000/graphql

Authorization header

Authorization: Bearer ps_test_YOUR_KEY

TEST mode uses Unisend, Pasts, and DPD test credentials. LIVE mode uses live credentials. Missing credentials fall back to fixtures. Stripe billing runs only in LIVE.

Open GraphQL Playground (schema explorer, not this guide)

TypeScript SDK

Install @pixel-shipping/sdk. It covers exactly the public operations — never admin schema.

pnpm add @pixel-shipping/sdk
import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

Quickstart

Typical shop checkout: get shipping options for a known size, pick nearby lockers, save a draft with phones and the merchant order id, then after packing look up that draft, purchase the label, download the PDF, and optionally create a return label.

GraphQL

query ShippingOptions($lengthMm: Int, $widthMm: Int, $heightMm: Int, $weightGrams: Int, $originCountry: CountryCode, $destinationCountry: CountryCode) {
  shippingOptions(lengthMm: $lengthMm, widthMm: $widthMm, heightMm: $heightMm, weightGrams: $weightGrams, originCountry: $originCountry, destinationCountry: $destinationCountry) {
    providerId
    sizeCode
    methods
    countries
    displayRate { cents currency }
  }
}

query SearchStations($countryCode: CountryCode!, $providerId: ProviderId, $latitude: Float, $longitude: Float) {
  searchStations(countryCode: $countryCode, providerId: $providerId, latitude: $latitude, longitude: $longitude) {
    id
    name
    line1
    city
    distanceMeters
  }
}

mutation CreateDraftLabel(
  $orderId: String!
  $providerId: ProviderId!
  $method: ShipmentMethod!
  $originCountry: CountryCode!
  $destinationCountry: CountryCode!
  $weightGrams: Int
  $senderName: String!
  $senderLine1: String!
  $senderCity: String!
  $senderPostalCode: String!
  $senderPhone: String!
  $recipientName: String!
  $recipientLine1: String!
  $recipientCity: String!
  $recipientPostalCode: String!
  $recipientPhone: String!
  $sizeCode: SizeCode
  $stationId: String
) {
  createDraftLabel(
    orderId: $orderId
    providerId: $providerId
    method: $method
    originCountry: $originCountry
    destinationCountry: $destinationCountry
    weightGrams: $weightGrams
    senderName: $senderName
    senderLine1: $senderLine1
    senderCity: $senderCity
    senderPostalCode: $senderPostalCode
    senderPhone: $senderPhone
    recipientName: $recipientName
    recipientLine1: $recipientLine1
    recipientCity: $recipientCity
    recipientPostalCode: $recipientPostalCode
    recipientPhone: $recipientPhone
    sizeCode: $sizeCode
    stationId: $stationId
  ) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    parentLabelId
    returnLabelId
  }
}

query Labels($orderId: String, $status: LabelStatus) {
  labels(orderId: $orderId, status: $status) {
    id
    status
    orderId
    stationId
  }
}

mutation PurchaseLabel($id: String!, $sizeCode: SizeCode, $weightGrams: Int) {
  purchaseLabel(id: $id, sizeCode: $sizeCode, weightGrams: $weightGrams) {
    id
    status
    sizeCode
    weightGrams
    trackingCode
    trackingUrl
  }
}

query DownloadLabelPdf($id: String!) {
  downloadLabelPdf(id: $id)
}

mutation CreateReturnLabel($id: String!) {
  createReturnLabel(id: $id) {
    id
    parentLabelId
    trackingCode
    trackingUrl
  }
}

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const options = await client.request(
  `query ShippingOptions($lengthMm: Int, $widthMm: Int, $heightMm: Int, $weightGrams: Int, $originCountry: CountryCode, $destinationCountry: CountryCode) {
    shippingOptions(lengthMm: $lengthMm, widthMm: $widthMm, heightMm: $heightMm, weightGrams: $weightGrams, originCountry: $originCountry, destinationCountry: $destinationCountry) {
      providerId sizeCode methods countries displayRate { cents currency }
    }
  }`,
  { lengthMm: 200, widthMm: 150, heightMm: 80, weightGrams: 500, originCountry: "LV", destinationCountry: "LT" },
);

const stations = await client.request(
  `query SearchStations($countryCode: CountryCode!, $providerId: ProviderId, $latitude: Float, $longitude: Float) {
    searchStations(countryCode: $countryCode, providerId: $providerId, latitude: $latitude, longitude: $longitude) {
      id name line1 city distanceMeters
    }
  }`,
  { countryCode: "LV", providerId: "UNISEND", latitude: 56.9496, longitude: 24.1052 },
);

const draft = await client.request(
  `mutation CreateDraftLabel($orderId: String!, $providerId: ProviderId!, $method: ShipmentMethod!, $originCountry: CountryCode!, $destinationCountry: CountryCode!, $weightGrams: Int, $senderName: String!, $senderLine1: String!, $senderCity: String!, $senderPostalCode: String!, $senderPhone: String!, $recipientName: String!, $recipientLine1: String!, $recipientCity: String!, $recipientPostalCode: String!, $recipientPhone: String!, $sizeCode: SizeCode, $stationId: String) {
    createDraftLabel(orderId: $orderId, providerId: $providerId, method: $method, originCountry: $originCountry, destinationCountry: $destinationCountry, weightGrams: $weightGrams, senderName: $senderName, senderLine1: $senderLine1, senderCity: $senderCity, senderPostalCode: $senderPostalCode, senderPhone: $senderPhone, recipientName: $recipientName, recipientLine1: $recipientLine1, recipientCity: $recipientCity, recipientPostalCode: $recipientPostalCode, recipientPhone: $recipientPhone, sizeCode: $sizeCode, stationId: $stationId) {
      id status providerId sizeCode originCountry destinationCountry weightGrams method orderId stationId parentLabelId returnLabelId
    }
  }`,
  {
    orderId: "ORD-1001",
    providerId: "UNISEND",
    method: "STATION_DROPOFF",
    originCountry: "LV",
    destinationCountry: "LT",
    senderName: "Acme SIA",
    senderLine1: "Brivibas iela 1",
    senderCity: "Riga",
    senderPostalCode: "LV-1010",
    senderPhone: "+37120000000",
    recipientName: "Jonas Petrauskas",
    recipientLine1: "Gedimino pr. 9",
    recipientCity: "Vilnius",
    recipientPostalCode: "01103",
    recipientPhone: "+37061234567",
    stationId: "LT-FIX-1",
  },
);

const pending = await client.request(
  `query Labels($orderId: String, $status: LabelStatus) {
    labels(orderId: $orderId, status: $status) { id status orderId stationId }
  }`,
  { orderId: "ORD-1001", status: "DRAFT" },
);

const purchased = await client.request(
  `mutation PurchaseLabel($id: String!) {
    purchaseLabel(id: $id, sizeCode: $sizeCode, weightGrams: $weightGrams) { id status sizeCode weightGrams trackingCode trackingUrl }
  }`,
  { id: pending.labels[0]?.id ?? draft.createDraftLabel.id, sizeCode: "M", weightGrams: 500 },
);

const pdf = await client.request(
  `query DownloadLabelPdf($id: String!) { downloadLabelPdf(id: $id) }`,
  { id: purchased.purchaseLabel.id },
);

const returned = await client.request(
  `mutation CreateReturnLabel($id: String!) {
    createReturnLabel(id: $id) { id parentLabelId trackingCode }
  }`,
  { id: purchased.purchaseLabel.id },
);

Catalog

catalog

Providers enabled for your organization, with methods, destination countries, sizeCodes that courier offers, and a “from” display rate for the cheapest offered size plus your markup. Pass originCountry (sender country; defaults to the organization sender or LV). destinationRates is the cheapest size on each origin → destination lane. Checkout should use shippingOptions.

GraphQL

query Catalog($originCountry: CountryCode) {
  catalog(originCountry: $originCountry) {
    providerId
    methods
    countries
    sizeCodes
    displayRate {
      cents
      currency
    }
    destinationRates {
      destinationCountry
      displayRate {
        cents
        currency
      }
    }
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query Catalog($originCountry: CountryCode) {\n  catalog(originCountry: $originCountry) {\n    providerId\n    methods\n    countries\n    sizeCodes\n    displayRate {\n      cents\n      currency\n    }\n    destinationRates {\n      destinationCountry\n      displayRate {\n        cents\n        currency\n      }\n    }\n  }\n}",
  "variables": {
    "originCountry": "LV"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query Catalog($originCountry: CountryCode) {
  catalog(originCountry: $originCountry) {
    providerId
    methods
    countries
    sizeCodes
    displayRate {
      cents
      currency
    }
    destinationRates {
      destinationCountry
      displayRate {
        cents
        currency
      }
    }
  }
}`,
  {
    "originCountry": "LV"
  },
);

recommendSize

Pick a size enum from dimensions and weight, or confirm a size you already chose. Pass providerId plus either sizeCode or length/width/height in millimetres and weightGrams.

Typical error codes: VALIDATION, SIZE_DOES_NOT_FIT, SIZE_NOT_OFFERED

GraphQL

query RecommendSize(
  $providerId: ProviderId!
  $sizeCode: SizeCode
  $lengthMm: Int
  $widthMm: Int
  $heightMm: Int
  $weightGrams: Int
) {
  recommendSize(
    providerId: $providerId
    sizeCode: $sizeCode
    lengthMm: $lengthMm
    widthMm: $widthMm
    heightMm: $heightMm
    weightGrams: $weightGrams
  )
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query RecommendSize(\n  $providerId: ProviderId!\n  $sizeCode: SizeCode\n  $lengthMm: Int\n  $widthMm: Int\n  $heightMm: Int\n  $weightGrams: Int\n) {\n  recommendSize(\n    providerId: $providerId\n    sizeCode: $sizeCode\n    lengthMm: $lengthMm\n    widthMm: $widthMm\n    heightMm: $heightMm\n    weightGrams: $weightGrams\n  )\n}",
  "variables": {
    "providerId": "UNISEND",
    "lengthMm": 200,
    "widthMm": 150,
    "heightMm": 80,
    "weightGrams": 500
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query RecommendSize(
  $providerId: ProviderId!
  $sizeCode: SizeCode
  $lengthMm: Int
  $widthMm: Int
  $heightMm: Int
  $weightGrams: Int
) {
  recommendSize(
    providerId: $providerId
    sizeCode: $sizeCode
    lengthMm: $lengthMm
    widthMm: $widthMm
    heightMm: $heightMm
    weightGrams: $weightGrams
  )
}`,
  {
    "providerId": "UNISEND",
    "lengthMm": 200,
    "widthMm": 150,
    "heightMm": 80,
    "weightGrams": 500
  },
);

shippingOptions

Checkout quote: send a size enum or dimensions and weight, plus originCountry and destinationCountry (LV, EE, or LT). Returns enabled providers that can ship that lane, the resolved sizeCode, and the display rate (per-size base for the lane plus your markup). Omit destinationCountry to get one option per enabled destination. Providers that cannot take the size are omitted.

Typical error codes: VALIDATION

GraphQL

query ShippingOptions(
  $sizeCode: SizeCode
  $lengthMm: Int
  $widthMm: Int
  $heightMm: Int
  $weightGrams: Int
  $originCountry: CountryCode
  $destinationCountry: CountryCode
) {
  shippingOptions(
    sizeCode: $sizeCode
    lengthMm: $lengthMm
    widthMm: $widthMm
    heightMm: $heightMm
    weightGrams: $weightGrams
    originCountry: $originCountry
    destinationCountry: $destinationCountry
  ) {
    providerId
    sizeCode
    methods
    countries
    displayRate {
      cents
      currency
    }
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query ShippingOptions(\n  $sizeCode: SizeCode\n  $lengthMm: Int\n  $widthMm: Int\n  $heightMm: Int\n  $weightGrams: Int\n  $originCountry: CountryCode\n  $destinationCountry: CountryCode\n) {\n  shippingOptions(\n    sizeCode: $sizeCode\n    lengthMm: $lengthMm\n    widthMm: $widthMm\n    heightMm: $heightMm\n    weightGrams: $weightGrams\n    originCountry: $originCountry\n    destinationCountry: $destinationCountry\n  ) {\n    providerId\n    sizeCode\n    methods\n    countries\n    displayRate {\n      cents\n      currency\n    }\n  }\n}",
  "variables": {
    "lengthMm": 200,
    "widthMm": 150,
    "heightMm": 80,
    "weightGrams": 500,
    "originCountry": "LV",
    "destinationCountry": "LT"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query ShippingOptions(
  $sizeCode: SizeCode
  $lengthMm: Int
  $widthMm: Int
  $heightMm: Int
  $weightGrams: Int
  $originCountry: CountryCode
  $destinationCountry: CountryCode
) {
  shippingOptions(
    sizeCode: $sizeCode
    lengthMm: $lengthMm
    widthMm: $widthMm
    heightMm: $heightMm
    weightGrams: $weightGrams
    originCountry: $originCountry
    destinationCountry: $destinationCountry
  ) {
    providerId
    sizeCode
    methods
    countries
    displayRate {
      cents
      currency
    }
  }
}`,
  {
    "lengthMm": 200,
    "widthMm": 150,
    "heightMm": 80,
    "weightGrams": 500,
    "originCountry": "LV",
    "destinationCountry": "LT"
  },
);

Labels

createDraftLabel

Reserve who, where, and which locker without buying from the courier. Status is DRAFT. orderId is required (your shop order id). Same address and phone fields as createLabel. sizeCode, dimensions, and weightGrams are optional — omit them and choose the compartment and weight on purchaseLabel. stationId is the destination locker from searchStations — omit it for terminal-to-home (T2H). No PDF, tracking, or Stripe charge until purchaseLabel.

Typical error codes: VALIDATION, SIZE_DOES_NOT_FIT, SIZE_NOT_OFFERED, COUNTRY_NOT_SUPPORTED

GraphQL

mutation CreateDraftLabel(
  $orderId: String!
  $providerId: ProviderId!
  $method: ShipmentMethod!
  $originCountry: CountryCode!
  $destinationCountry: CountryCode!
  $weightGrams: Int
  $senderName: String!
  $senderLine1: String!
  $senderCity: String!
  $senderPostalCode: String!
  $senderPhone: String!
  $recipientName: String!
  $recipientLine1: String!
  $recipientCity: String!
  $recipientPostalCode: String!
  $recipientPhone: String!
  $sizeCode: SizeCode
  $stationId: String
  $lengthMm: Int
  $widthMm: Int
  $heightMm: Int
) {
  createDraftLabel(
    orderId: $orderId
    providerId: $providerId
    method: $method
    originCountry: $originCountry
    destinationCountry: $destinationCountry
    weightGrams: $weightGrams
    senderName: $senderName
    senderLine1: $senderLine1
    senderCity: $senderCity
    senderPostalCode: $senderPostalCode
    senderPhone: $senderPhone
    recipientName: $recipientName
    recipientLine1: $recipientLine1
    recipientCity: $recipientCity
    recipientPostalCode: $recipientPostalCode
    recipientPhone: $recipientPhone
    sizeCode: $sizeCode
    stationId: $stationId
    lengthMm: $lengthMm
    widthMm: $widthMm
    heightMm: $heightMm
  ) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "mutation CreateDraftLabel(\n  $orderId: String!\n  $providerId: ProviderId!\n  $method: ShipmentMethod!\n  $originCountry: CountryCode!\n  $destinationCountry: CountryCode!\n  $weightGrams: Int\n  $senderName: String!\n  $senderLine1: String!\n  $senderCity: String!\n  $senderPostalCode: String!\n  $senderPhone: String!\n  $recipientName: String!\n  $recipientLine1: String!\n  $recipientCity: String!\n  $recipientPostalCode: String!\n  $recipientPhone: String!\n  $sizeCode: SizeCode\n  $stationId: String\n  $lengthMm: Int\n  $widthMm: Int\n  $heightMm: Int\n) {\n  createDraftLabel(\n    orderId: $orderId\n    providerId: $providerId\n    method: $method\n    originCountry: $originCountry\n    destinationCountry: $destinationCountry\n    weightGrams: $weightGrams\n    senderName: $senderName\n    senderLine1: $senderLine1\n    senderCity: $senderCity\n    senderPostalCode: $senderPostalCode\n    senderPhone: $senderPhone\n    recipientName: $recipientName\n    recipientLine1: $recipientLine1\n    recipientCity: $recipientCity\n    recipientPostalCode: $recipientPostalCode\n    recipientPhone: $recipientPhone\n    sizeCode: $sizeCode\n    stationId: $stationId\n    lengthMm: $lengthMm\n    widthMm: $widthMm\n    heightMm: $heightMm\n  ) {\n    id\n    status\n    providerId\n    sizeCode\n    originCountry\n    destinationCountry\n    method\n    orderId\n    stationId\n    weightGrams\n    trackingCode\n    trackingUrl\n    parentLabelId\n    returnLabelId\n  }\n}",
  "variables": {
    "orderId": "ORD-1001",
    "providerId": "UNISEND",
    "method": "STATION_DROPOFF",
    "originCountry": "LV",
    "destinationCountry": "LT",
    "senderName": "Acme SIA",
    "senderLine1": "Brivibas iela 1",
    "senderCity": "Riga",
    "senderPostalCode": "LV-1010",
    "senderPhone": "+37120000000",
    "recipientName": "Jonas Petrauskas",
    "recipientLine1": "Gedimino pr. 9",
    "recipientCity": "Vilnius",
    "recipientPostalCode": "01103",
    "recipientPhone": "+37061234567",
    "stationId": "LT-FIX-1"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `mutation CreateDraftLabel(
  $orderId: String!
  $providerId: ProviderId!
  $method: ShipmentMethod!
  $originCountry: CountryCode!
  $destinationCountry: CountryCode!
  $weightGrams: Int
  $senderName: String!
  $senderLine1: String!
  $senderCity: String!
  $senderPostalCode: String!
  $senderPhone: String!
  $recipientName: String!
  $recipientLine1: String!
  $recipientCity: String!
  $recipientPostalCode: String!
  $recipientPhone: String!
  $sizeCode: SizeCode
  $stationId: String
  $lengthMm: Int
  $widthMm: Int
  $heightMm: Int
) {
  createDraftLabel(
    orderId: $orderId
    providerId: $providerId
    method: $method
    originCountry: $originCountry
    destinationCountry: $destinationCountry
    weightGrams: $weightGrams
    senderName: $senderName
    senderLine1: $senderLine1
    senderCity: $senderCity
    senderPostalCode: $senderPostalCode
    senderPhone: $senderPhone
    recipientName: $recipientName
    recipientLine1: $recipientLine1
    recipientCity: $recipientCity
    recipientPostalCode: $recipientPostalCode
    recipientPhone: $recipientPhone
    sizeCode: $sizeCode
    stationId: $stationId
    lengthMm: $lengthMm
    widthMm: $widthMm
    heightMm: $heightMm
  ) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}`,
  {
    "orderId": "ORD-1001",
    "providerId": "UNISEND",
    "method": "STATION_DROPOFF",
    "originCountry": "LV",
    "destinationCountry": "LT",
    "senderName": "Acme SIA",
    "senderLine1": "Brivibas iela 1",
    "senderCity": "Riga",
    "senderPostalCode": "LV-1010",
    "senderPhone": "+37120000000",
    "recipientName": "Jonas Petrauskas",
    "recipientLine1": "Gedimino pr. 9",
    "recipientCity": "Vilnius",
    "recipientPostalCode": "01103",
    "recipientPhone": "+37061234567",
    "stationId": "LT-FIX-1"
  },
);

purchaseLabel

Buy a DRAFT label. Pass the label id. If the draft has no sizeCode or weightGrams yet, pass them here — sizeCode must be one of that courier’s catalog.sizeCodes (for example DPD has no XS). Drafts that already stored size and weight still purchase with id only. Returns PURCHASED with tracking. Live keys bill postage and the platform fee.

Typical error codes: NOT_FOUND, VALIDATION, SIZE_NOT_OFFERED, PROVIDER_FAILURE, INSUFFICIENT_CREDIT, BILLING_REQUIRED, BILLING_PAST_DUE

GraphQL

mutation PurchaseLabel($id: String!, $sizeCode: SizeCode, $weightGrams: Int) {
  purchaseLabel(id: $id, sizeCode: $sizeCode, weightGrams: $weightGrams) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "mutation PurchaseLabel($id: String!, $sizeCode: SizeCode, $weightGrams: Int) {\n  purchaseLabel(id: $id, sizeCode: $sizeCode, weightGrams: $weightGrams) {\n    id\n    status\n    providerId\n    sizeCode\n    originCountry\n    destinationCountry\n    method\n    orderId\n    stationId\n    weightGrams\n    trackingCode\n    trackingUrl\n    parentLabelId\n    returnLabelId\n  }\n}",
  "variables": {
    "id": "label_01HZX",
    "sizeCode": "M",
    "weightGrams": 500
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `mutation PurchaseLabel($id: String!, $sizeCode: SizeCode, $weightGrams: Int) {
  purchaseLabel(id: $id, sizeCode: $sizeCode, weightGrams: $weightGrams) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}`,
  {
    "id": "label_01HZX",
    "sizeCode": "M",
    "weightGrams": 500
  },
);

createLabel

Buy a Unisend, Pasts, or DPD label in one request. Origin and destination must be LV, EE, or LT. senderPhone and recipientPhone are required Baltic E.164 numbers (+370, +371, or +372). Locker delivery also requires a mobile recipientPhone. method plus stationId choose the plan: courier without stationId is home-to-home; courier with stationId is home-to-terminal; station drop-off without stationId is terminal-to-home; station drop-off with stationId is terminal-to-terminal. stationId is Station.id from searchStations, not a GraphQL enum. Pass sizeCode from shippingOptions, or dimensions so the API can recommend a size. Optional orderId stores your shop order id. Prefer createDraftLabel at checkout if you will pack later.

Typical error codes: VALIDATION, SIZE_DOES_NOT_FIT, SIZE_NOT_OFFERED, COUNTRY_NOT_SUPPORTED, PROVIDER_FAILURE, INSUFFICIENT_CREDIT, BILLING_REQUIRED, BILLING_PAST_DUE

GraphQL

mutation CreateLabel(
  $providerId: ProviderId!
  $method: ShipmentMethod!
  $originCountry: CountryCode!
  $destinationCountry: CountryCode!
  $weightGrams: Int!
  $senderName: String!
  $senderLine1: String!
  $senderCity: String!
  $senderPostalCode: String!
  $senderPhone: String!
  $recipientName: String!
  $recipientLine1: String!
  $recipientCity: String!
  $recipientPostalCode: String!
  $recipientPhone: String!
  $sizeCode: SizeCode
  $stationId: String
  $orderId: String
  $lengthMm: Int
  $widthMm: Int
  $heightMm: Int
) {
  createLabel(
    providerId: $providerId
    method: $method
    originCountry: $originCountry
    destinationCountry: $destinationCountry
    weightGrams: $weightGrams
    senderName: $senderName
    senderLine1: $senderLine1
    senderCity: $senderCity
    senderPostalCode: $senderPostalCode
    senderPhone: $senderPhone
    recipientName: $recipientName
    recipientLine1: $recipientLine1
    recipientCity: $recipientCity
    recipientPostalCode: $recipientPostalCode
    recipientPhone: $recipientPhone
    sizeCode: $sizeCode
    stationId: $stationId
    orderId: $orderId
    lengthMm: $lengthMm
    widthMm: $widthMm
    heightMm: $heightMm
  ) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "mutation CreateLabel(\n  $providerId: ProviderId!\n  $method: ShipmentMethod!\n  $originCountry: CountryCode!\n  $destinationCountry: CountryCode!\n  $weightGrams: Int!\n  $senderName: String!\n  $senderLine1: String!\n  $senderCity: String!\n  $senderPostalCode: String!\n  $senderPhone: String!\n  $recipientName: String!\n  $recipientLine1: String!\n  $recipientCity: String!\n  $recipientPostalCode: String!\n  $recipientPhone: String!\n  $sizeCode: SizeCode\n  $stationId: String\n  $orderId: String\n  $lengthMm: Int\n  $widthMm: Int\n  $heightMm: Int\n) {\n  createLabel(\n    providerId: $providerId\n    method: $method\n    originCountry: $originCountry\n    destinationCountry: $destinationCountry\n    weightGrams: $weightGrams\n    senderName: $senderName\n    senderLine1: $senderLine1\n    senderCity: $senderCity\n    senderPostalCode: $senderPostalCode\n    senderPhone: $senderPhone\n    recipientName: $recipientName\n    recipientLine1: $recipientLine1\n    recipientCity: $recipientCity\n    recipientPostalCode: $recipientPostalCode\n    recipientPhone: $recipientPhone\n    sizeCode: $sizeCode\n    stationId: $stationId\n    orderId: $orderId\n    lengthMm: $lengthMm\n    widthMm: $widthMm\n    heightMm: $heightMm\n  ) {\n    id\n    status\n    providerId\n    sizeCode\n    originCountry\n    destinationCountry\n    method\n    orderId\n    stationId\n    weightGrams\n    trackingCode\n    trackingUrl\n    parentLabelId\n    returnLabelId\n  }\n}",
  "variables": {
    "providerId": "UNISEND",
    "method": "STATION_DROPOFF",
    "originCountry": "LV",
    "destinationCountry": "LT",
    "weightGrams": 500,
    "senderName": "Acme SIA",
    "senderLine1": "Brivibas iela 1",
    "senderCity": "Riga",
    "senderPostalCode": "LV-1010",
    "senderPhone": "+37120000000",
    "recipientName": "Jonas Petrauskas",
    "recipientLine1": "Gedimino pr. 9",
    "recipientCity": "Vilnius",
    "recipientPostalCode": "01103",
    "recipientPhone": "+37061234567",
    "sizeCode": "S",
    "stationId": "LT-FIX-1",
    "orderId": "ORD-1001"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `mutation CreateLabel(
  $providerId: ProviderId!
  $method: ShipmentMethod!
  $originCountry: CountryCode!
  $destinationCountry: CountryCode!
  $weightGrams: Int!
  $senderName: String!
  $senderLine1: String!
  $senderCity: String!
  $senderPostalCode: String!
  $senderPhone: String!
  $recipientName: String!
  $recipientLine1: String!
  $recipientCity: String!
  $recipientPostalCode: String!
  $recipientPhone: String!
  $sizeCode: SizeCode
  $stationId: String
  $orderId: String
  $lengthMm: Int
  $widthMm: Int
  $heightMm: Int
) {
  createLabel(
    providerId: $providerId
    method: $method
    originCountry: $originCountry
    destinationCountry: $destinationCountry
    weightGrams: $weightGrams
    senderName: $senderName
    senderLine1: $senderLine1
    senderCity: $senderCity
    senderPostalCode: $senderPostalCode
    senderPhone: $senderPhone
    recipientName: $recipientName
    recipientLine1: $recipientLine1
    recipientCity: $recipientCity
    recipientPostalCode: $recipientPostalCode
    recipientPhone: $recipientPhone
    sizeCode: $sizeCode
    stationId: $stationId
    orderId: $orderId
    lengthMm: $lengthMm
    widthMm: $widthMm
    heightMm: $heightMm
  ) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}`,
  {
    "providerId": "UNISEND",
    "method": "STATION_DROPOFF",
    "originCountry": "LV",
    "destinationCountry": "LT",
    "weightGrams": 500,
    "senderName": "Acme SIA",
    "senderLine1": "Brivibas iela 1",
    "senderCity": "Riga",
    "senderPostalCode": "LV-1010",
    "senderPhone": "+37120000000",
    "recipientName": "Jonas Petrauskas",
    "recipientLine1": "Gedimino pr. 9",
    "recipientCity": "Vilnius",
    "recipientPostalCode": "01103",
    "recipientPhone": "+37061234567",
    "sizeCode": "S",
    "stationId": "LT-FIX-1",
    "orderId": "ORD-1001"
  },
);

createReturnLabel

Print a return sticker for a purchased outbound label. Pass the outbound id. The new Label has parentLabelId set to that outbound; the outbound then exposes returnLabelId. Use downloadLabelPdf, trackLabel, and cancelLabel on either id. At most one return per outbound. Live DPD and Pasts do not offer returns yet. Unisend contracts must have the return service enabled.

Typical error codes: NOT_FOUND, VALIDATION, PROVIDER_FAILURE, INSUFFICIENT_CREDIT, BILLING_REQUIRED, BILLING_PAST_DUE

GraphQL

mutation CreateReturnLabel($id: String!) {
  createReturnLabel(id: $id) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "mutation CreateReturnLabel($id: String!) {\n  createReturnLabel(id: $id) {\n    id\n    status\n    providerId\n    sizeCode\n    originCountry\n    destinationCountry\n    method\n    orderId\n    stationId\n    weightGrams\n    trackingCode\n    trackingUrl\n    parentLabelId\n    returnLabelId\n  }\n}",
  "variables": {
    "id": "label_01HZX"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `mutation CreateReturnLabel($id: String!) {
  createReturnLabel(id: $id) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}`,
  {
    "id": "label_01HZX"
  },
);

labels

List labels for your organization, newest first. Pass orderId to fetch labels for a shop order, and status (for example DRAFT) to filter pending purchases. Return labels include parentLabelId; an outbound that already has a return includes returnLabelId.

GraphQL

query Labels($orderId: String, $status: LabelStatus) {
  labels(orderId: $orderId, status: $status) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query Labels($orderId: String, $status: LabelStatus) {\n  labels(orderId: $orderId, status: $status) {\n    id\n    status\n    providerId\n    sizeCode\n    originCountry\n    destinationCountry\n    method\n    orderId\n    stationId\n    weightGrams\n    trackingCode\n    trackingUrl\n    parentLabelId\n    returnLabelId\n  }\n}",
  "variables": {
    "orderId": "ORD-1001",
    "status": "DRAFT"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query Labels($orderId: String, $status: LabelStatus) {
  labels(orderId: $orderId, status: $status) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}`,
  {
    "orderId": "ORD-1001",
    "status": "DRAFT"
  },
);

label

Fetch one label by id, including status, originCountry, destinationCountry, orderId, locker stationId, nullable sizeCode and weightGrams, tracking, parentLabelId (on a return), and returnLabelId (on an outbound once a return exists).

Typical error codes: NOT_FOUND

GraphQL

query Label($id: String!) {
  label(id: $id) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query Label($id: String!) {\n  label(id: $id) {\n    id\n    status\n    providerId\n    sizeCode\n    originCountry\n    destinationCountry\n    method\n    orderId\n    stationId\n    weightGrams\n    trackingCode\n    trackingUrl\n    parentLabelId\n    returnLabelId\n  }\n}",
  "variables": {
    "id": "label_01HZX"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query Label($id: String!) {
  label(id: $id) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}`,
  {
    "id": "label_01HZX"
  },
);

trackLabel

Refresh tracking from the courier (or the test fixture) and return the updated label.

Typical error codes: NOT_FOUND, PROVIDER_FAILURE

GraphQL

query TrackLabel($id: String!) {
  trackLabel(id: $id) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query TrackLabel($id: String!) {\n  trackLabel(id: $id) {\n    id\n    status\n    providerId\n    sizeCode\n    originCountry\n    destinationCountry\n    method\n    orderId\n    stationId\n    weightGrams\n    trackingCode\n    trackingUrl\n    parentLabelId\n    returnLabelId\n  }\n}",
  "variables": {
    "id": "label_01HZX"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query TrackLabel($id: String!) {
  trackLabel(id: $id) {
    id
    status
    providerId
    sizeCode
    originCountry
    destinationCountry
    method
    orderId
    stationId
    weightGrams
    trackingCode
    trackingUrl
    parentLabelId
    returnLabelId
  }
}`,
  {
    "id": "label_01HZX"
  },
);

downloadLabelPdf

Returns the label PDF as a data URL. Works for the outbound id or the return id from createReturnLabel. Test PDFs are watermarked. In-memory PDFs are gone after the API process restarts.

Typical error codes: NOT_FOUND

GraphQL

query DownloadLabelPdf($id: String!) {
  downloadLabelPdf(id: $id)
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query DownloadLabelPdf($id: String!) {\n  downloadLabelPdf(id: $id)\n}",
  "variables": {
    "id": "label_01HZX"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query DownloadLabelPdf($id: String!) {
  downloadLabelPdf(id: $id)
}`,
  {
    "id": "label_01HZX"
  },
);

cancelLabel

Cancel a purchased label when the courier still allows it. Venipak has no courier cancel API: Pixel marks the label cancelled and releases the hold; the Venipak pack itself is not voided. Cancelling an outbound also cancels a still-cancellable linked return. Cancelling the return id only cancels the return. Returns true when the cancel succeeded.

Typical error codes: NOT_FOUND, VALIDATION, PROVIDER_FAILURE

GraphQL

mutation CancelLabel($id: String!) {
  cancelLabel(id: $id)
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "mutation CancelLabel($id: String!) {\n  cancelLabel(id: $id)\n}",
  "variables": {
    "id": "label_01HZX"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `mutation CancelLabel($id: String!) {
  cancelLabel(id: $id)
}`,
  {
    "id": "label_01HZX"
  },
);

Stations

searchStations

Parcel lockers and pickup points for a Baltic country (LV, EE, or LT). Pass providerId after the shopper picks a vendor. With latitude and longitude, results include distanceMeters and are sorted nearest first. Use Station.id as stationId on createLabel or createDraftLabel — lockers are not a GraphQL enum.

Typical error codes: VALIDATION, COUNTRY_NOT_SUPPORTED

GraphQL

query SearchStations(
  $countryCode: CountryCode!
  $providerId: ProviderId
  $latitude: Float
  $longitude: Float
  $limit: Int
) {
  searchStations(
    countryCode: $countryCode
    providerId: $providerId
    latitude: $latitude
    longitude: $longitude
    limit: $limit
  ) {
    id
    providerId
    countryCode
    name
    line1
    city
    postalCode
    latitude
    longitude
    distanceMeters
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query SearchStations(\n  $countryCode: CountryCode!\n  $providerId: ProviderId\n  $latitude: Float\n  $longitude: Float\n  $limit: Int\n) {\n  searchStations(\n    countryCode: $countryCode\n    providerId: $providerId\n    latitude: $latitude\n    longitude: $longitude\n    limit: $limit\n  ) {\n    id\n    providerId\n    countryCode\n    name\n    line1\n    city\n    postalCode\n    latitude\n    longitude\n    distanceMeters\n  }\n}",
  "variables": {
    "countryCode": "LV",
    "providerId": "UNISEND",
    "latitude": 56.9496,
    "longitude": 24.1052,
    "limit": 10
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query SearchStations(
  $countryCode: CountryCode!
  $providerId: ProviderId
  $latitude: Float
  $longitude: Float
  $limit: Int
) {
  searchStations(
    countryCode: $countryCode
    providerId: $providerId
    latitude: $latitude
    longitude: $longitude
    limit: $limit
  ) {
    id
    providerId
    countryCode
    name
    line1
    city
    postalCode
    latitude
    longitude
    distanceMeters
  }
}`,
  {
    "countryCode": "LV",
    "providerId": "UNISEND",
    "latitude": 56.9496,
    "longitude": 24.1052,
    "limit": 10
  },
);

Webhooks

registerWebhookEndpoint

Register an HTTPS URL that should receive label events. Outbound delivery is partial in v1.

Typical error codes: VALIDATION

GraphQL

mutation RegisterWebhookEndpoint($url: String!) {
  registerWebhookEndpoint(url: $url) {
    id
    url
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "mutation RegisterWebhookEndpoint($url: String!) {\n  registerWebhookEndpoint(url: $url) {\n    id\n    url\n  }\n}",
  "variables": {
    "url": "https://merchant.example/webhooks/pixel-shipping"
  }
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `mutation RegisterWebhookEndpoint($url: String!) {
  registerWebhookEndpoint(url: $url) {
    id
    url
  }
}`,
  {
    "url": "https://merchant.example/webhooks/pixel-shipping"
  },
);

webhookEndpoints

List webhook URLs already registered for your organization.

GraphQL

query WebhookEndpoints {
  webhookEndpoints {
    id
    url
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query WebhookEndpoints {\n  webhookEndpoints {\n    id\n    url\n  }\n}"
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query WebhookEndpoints {
  webhookEndpoints {
    id
    url
  }
}`,
);

Usage

ownUsage

Running platform fee, postage, and total for live API-key traffic. Test-key calls are not billed.

GraphQL

query OwnUsage {
  ownUsage {
    platformFee {
      cents
      currency
    }
    postage {
      cents
      currency
    }
    runningCost {
      cents
      currency
    }
  }
}

curl

curl -sS http://localhost:4000/graphql \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer ps_test_YOUR_KEY' \
  -d '{
  "query": "query OwnUsage {\n  ownUsage {\n    platformFee {\n      cents\n      currency\n    }\n    postage {\n      cents\n      currency\n    }\n    runningCost {\n      cents\n      currency\n    }\n  }\n}"
}'

SDK

import { createPixelShippingClient } from "@pixel-shipping/sdk";

const client = createPixelShippingClient({
  apiUrl: "http://localhost:4000/graphql",
  apiKey: "ps_test_YOUR_KEY",
});

const data = await client.request(
  `query OwnUsage {
  ownUsage {
    platformFee {
      cents
      currency
    }
    postage {
      cents
      currency
    }
    runningCost {
      cents
      currency
    }
  }
}`,
);

Error codes

GraphQL still returns HTTP 200 for domain errors. Read errors[].extensions.code. VALIDATION errors also set extensions.field to the GraphQL argument name (for example senderPhone or stationId).

CodeMeaning
VALIDATIONA required argument is missing or invalid. extensions.field names the argument.
NOT_FOUNDThe label or resource does not exist in your organization.
SIZE_DOES_NOT_FITThe parcel does not fit the chosen size.
SIZE_NOT_OFFEREDThat size is not offered for the provider.
COUNTRY_NOT_SUPPORTEDOrigin or destination is outside LV, EE, and LT.
PROVIDER_FAILUREThe courier call failed. Retry or inspect the message.
UNAUTHENTICATEDThe bearer key is missing or rejected.
FORBIDDENThe key is valid but this operation is not allowed.
INSUFFICIENT_CREDITAvailable prepaid credit cannot cover this live label. Deposit or wait for a top-up.
BILLING_REQUIREDLive purchases need a completed deposit and a default payment method.
BILLING_PAST_DUEThe Stripe subscription or invoice needs attention before more live labels.

API keys, members, and billing live in the merchant dashboard (session auth). Super-admin operations are on /admin/graphql and are not in the SDK.