Skip to content

Orders

Read-only access to the orders stored against your carrier accounts. All three endpoints cover every license you own; pass license_key only if you want to narrow them to one carrier account.

License selection

license_key is optional on these endpoints. Supply a License's key to restrict the results to that carrier account; omit it and the lookup spans all of them. A key you do not own is a 403.


GET /orders

List the caller's orders for the selected license, newest first, cursor-paginated. Auth: client credentials. License: required.

Parameters

Query

FieldTypeRequiredDescription
license_keystringnoA License key to narrow the lookup to one carrier account. Omitted, it spans every license you own.
per_pageintegernoOrders per page. Defaults to 25, capped at 100.
cursorstringnoOpaque pagination cursor. Use the meta.next_cursor / meta.prev_cursor value returned by a previous call to page through results.

Example request

bash
curl --location 'https://app.shipos.co.il/api/v2/orders?per_page=25' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'
js
// Node.js 18+ / browsers — no dependencies
const query = new URLSearchParams({ per_page: '25' })

const response = await fetch(`https://app.shipos.co.il/api/v2/orders?${query}`, {
  headers: {
    'X-Client-Id': process.env.SHIPOS_CLIENT_ID,
    'X-Client-Secret': process.env.SHIPOS_CLIENT_SECRET,
    Accept: 'application/json',
  },
})

if (!response.ok) {
  const { error } = await response.json()
  throw new Error(`${error.code}: ${error.message}`)
}

const { data: orders, meta } = await response.json()

for (const order of orders) {
  console.log(order.order_id, order.total, order.currency)
}
console.log('next cursor:', meta.next_cursor)
php
<?php
// composer require guzzlehttp/guzzle

$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.shipos.co.il/api/v2/',
    'headers' => [
        'X-Client-Id' => getenv('SHIPOS_CLIENT_ID'),
        'X-Client-Secret' => getenv('SHIPOS_CLIENT_SECRET'),
        'Accept' => 'application/json',
    ],
]);

$response = $client->get('orders', ['query' => ['per_page' => 25]]);
$payload = json_decode($response->getBody()->getContents(), true);

foreach ($payload['data'] as $order) {
    echo $order['order_id'], ' ', $order['total'], ' ', $order['currency'], PHP_EOL;
}
echo 'next cursor: ', $payload['meta']['next_cursor'] ?? '-', PHP_EOL;
php
<?php

use Illuminate\Support\Facades\Http;

$payload = Http::withHeaders([
    'X-Client-Id' => config('services.shipos.client_id'),
    'X-Client-Secret' => config('services.shipos.client_secret'),
])
    ->acceptJson()
    ->get('https://app.shipos.co.il/api/v2/orders', ['per_page' => 25])
    ->throw()
    ->json();

foreach ($payload['data'] as $order) {
    logger()->info($order['order_id'].' '.$order['total'].' '.$order['currency']);
}
logger()->info('next cursor: '.($payload['meta']['next_cursor'] ?? '-'));
python
# pip install httpx
import os

import httpx

response = httpx.get(
    "https://app.shipos.co.il/api/v2/orders",
    params={"per_page": 25},
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
)
response.raise_for_status()
payload = response.json()

for order in payload["data"]:
    print(order["order_id"], order["total"], order["currency"])
print("next cursor:", payload["meta"]["next_cursor"])
go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
)

type ordersResponse struct {
	Data []struct {
		OrderID  string `json:"order_id"`
		Total    string `json:"total"`
		Currency string `json:"currency"`
	} `json:"data"`
	Meta struct {
		NextCursor *string `json:"next_cursor"`
	} `json:"meta"`
}

func main() {
	query := url.Values{"per_page": {"25"}}
	req, _ := http.NewRequest("GET",
		"https://app.shipos.co.il/api/v2/orders?"+query.Encode(), nil)
	req.Header.Set("X-Client-Id", os.Getenv("SHIPOS_CLIENT_ID"))
	req.Header.Set("X-Client-Secret", os.Getenv("SHIPOS_CLIENT_SECRET"))
	req.Header.Set("Accept", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	var payload ordersResponse
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	for _, order := range payload.Data {
		fmt.Println(order.OrderID, order.Total, order.Currency)
	}
}
java
// Java 17+ — java.net.http, no dependencies (parse with Jackson/Gson)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class ShipOsOrders {
    public static void main(String[] args) throws Exception {
        String query = "per_page=25";

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/orders?" + query))
            .header("X-Client-Id", System.getenv("SHIPOS_CLIENT_ID"))
            .header("X-Client-Secret", System.getenv("SHIPOS_CLIENT_SECRET"))
            .header("Accept", "application/json")
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 200) {
            throw new RuntimeException("ShipOS error: " + response.body());
        }

        System.out.println(response.body()); // {"data":[...],"meta":{...}}
    }
}
csharp
// .NET 8+ — System.Net.Http.Json
using System.Net.Http.Json;
using System.Text.Json;

using var http = new HttpClient
{
    BaseAddress = new Uri("https://app.shipos.co.il/api/v2/"),
};
http.DefaultRequestHeaders.Add("X-Client-Id",
    Environment.GetEnvironmentVariable("SHIPOS_CLIENT_ID"));
http.DefaultRequestHeaders.Add("X-Client-Secret",
    Environment.GetEnvironmentVariable("SHIPOS_CLIENT_SECRET"));

var payload = await http.GetFromJsonAsync<JsonDocument>("orders?per_page=25")
    ?? throw new InvalidOperationException("Empty response");

foreach (var order in payload.RootElement.GetProperty("data").EnumerateArray())
{
    Console.WriteLine($"{order.GetProperty("order_id").GetString()} " +
        $"{order.GetProperty("total").GetString()}");
}
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/orders")
uri.query = URI.encode_www_form(per_page: 25)

request = Net::HTTP::Get.new(uri)
request["X-Client-Id"] = ENV.fetch("SHIPOS_CLIENT_ID")
request["X-Client-Secret"] = ENV.fetch("SHIPOS_CLIENT_SECRET")
request["Accept"] = "application/json"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

raise "ShipOS error: #{response.body}" unless response.is_a?(Net::HTTPSuccess)

payload = JSON.parse(response.body)

payload["data"].each { |order| puts "#{order["order_id"]} #{order["total"]}" }
puts "next cursor: #{payload.dig("meta", "next_cursor")}"
rust
// [dependencies]
// reqwest = { version = "0.12", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
// serde_json = "1"
use serde_json::Value;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let payload: Value = reqwest::Client::new()
        .get("https://app.shipos.co.il/api/v2/orders")
        .query(&[("per_page", "25")])
        .header("X-Client-Id", std::env::var("SHIPOS_CLIENT_ID")?)
        .header("X-Client-Secret", std::env::var("SHIPOS_CLIENT_SECRET")?)
        .header("Accept", "application/json")
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;

    if let Some(orders) = payload["data"].as_array() {
        for order in orders {
            println!("{} {}", order["order_id"], order["total"]);
        }
    }
    println!("next cursor: {}", payload["meta"]["next_cursor"]);
    Ok(())
}

Response 200

The list is cursor-paginated. Each item is an order (see the field reference under GET /orders/{order}). The shipments key is omitted from list items — it is only present when the order's shipments relation is loaded, which happens on the single-order endpoint.

json
{
  "data": [
    {
      "id": 84213,
      "order_id": "19602",
      "number": "19602",
      "source": "woocommerce",
      "total": "245.00",
      "currency": "ILS",
      "billing": {
        "first_name": "Dana",
        "last_name": "Levi",
        "address_1": "Herzl 10",
        "city": "Tel Aviv",
        "email": "dana@example.com",
        "phone": "0521234567"
      },
      "shipping": {
        "first_name": "Dana",
        "last_name": "Levi",
        "address_1": "Herzl 10",
        "city": "Tel Aviv"
      },
      "created_at": "2026-07-20T08:14:11.000000Z",
      "updated_at": "2026-07-20T08:15:02.000000Z"
    }
  ],
  "links": {
    "first": null,
    "last": null,
    "prev": null,
    "next": "https://app.shipos.co.il/api/v2/orders?cursor=eyJpZCI6ODQyMTN9"
  },
  "meta": {
    "path": "https://app.shipos.co.il/api/v2/orders",
    "per_page": 25,
    "next_cursor": "eyJpZCI6ODQyMTN9",
    "prev_cursor": null
  }
}

billing and shipping are passed through as stored on the order, so their exact keys vary by source platform.

Errors

StatuscodeWhen
401unauthenticatedMissing or invalid client credentials.
403forbiddenThe given license_key is not owned by you.

GET /orders/

Return a single order together with its shipments. Auth: client credentials. License: required.

Parameters

Path

FieldTypeRequiredDescription
orderstringyesThe external (platform) order id (order_id) of the order — the store's own order identifier, not the internal numeric id. Must belong to the selected license.

Query

FieldTypeRequiredDescription
license_keystringnoA License key to narrow the lookup to one carrier account. Omitted, it spans every license you own.

Example request

bash
curl --location 'https://app.shipos.co.il/api/v2/orders/19602' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'
js
// Node.js 18+ / browsers — no dependencies
const orderId = '19602'

const response = await fetch(`https://app.shipos.co.il/api/v2/orders/${orderId}`, {
  headers: {
    'X-Client-Id': process.env.SHIPOS_CLIENT_ID,
    'X-Client-Secret': process.env.SHIPOS_CLIENT_SECRET,
    Accept: 'application/json',
  },
})

if (!response.ok) {
  const { error } = await response.json()
  throw new Error(`${error.code}: ${error.message}`)
}

const { data: order } = await response.json()

console.log(order.order_id, order.total, order.currency)
for (const shipment of order.shipments) {
  console.log(shipment.tracking_code, shipment.status?.description)
}
php
<?php
// composer require guzzlehttp/guzzle

$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.shipos.co.il/api/v2/',
    'headers' => [
        'X-Client-Id' => getenv('SHIPOS_CLIENT_ID'),
        'X-Client-Secret' => getenv('SHIPOS_CLIENT_SECRET'),
        'Accept' => 'application/json',
    ],
]);

$order = json_decode(
    $client->get('orders/19602')->getBody()->getContents(),
    true,
)['data'];

echo $order['order_id'], ' ', $order['total'], PHP_EOL;
foreach ($order['shipments'] as $shipment) {
    echo $shipment['tracking_code'], PHP_EOL;
}
php
<?php

use Illuminate\Support\Facades\Http;

$order = Http::withHeaders([
    'X-Client-Id' => config('services.shipos.client_id'),
    'X-Client-Secret' => config('services.shipos.client_secret'),
])
    ->acceptJson()
    ->get('https://app.shipos.co.il/api/v2/orders/19602')
    ->throw()
    ->json('data');

logger()->info($order['order_id'].' '.$order['total']);
foreach ($order['shipments'] as $shipment) {
    logger()->info($shipment['tracking_code']);
}
python
# pip install httpx
import os

import httpx

response = httpx.get(
    "https://app.shipos.co.il/api/v2/orders/19602",
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
)
response.raise_for_status()
order = response.json()["data"]

print(order["order_id"], order["total"], order["currency"])
for shipment in order["shipments"]:
    print(shipment["tracking_code"])
go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

type orderResponse struct {
	Data struct {
		OrderID   string `json:"order_id"`
		Total     string `json:"total"`
		Shipments []struct {
			TrackingCode string `json:"tracking_code"`
		} `json:"shipments"`
	} `json:"data"`
}

func main() {
	req, _ := http.NewRequest("GET",
		"https://app.shipos.co.il/api/v2/orders/19602", nil)
	req.Header.Set("X-Client-Id", os.Getenv("SHIPOS_CLIENT_ID"))
	req.Header.Set("X-Client-Secret", os.Getenv("SHIPOS_CLIENT_SECRET"))
	req.Header.Set("Accept", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	var payload orderResponse
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	fmt.Println(payload.Data.OrderID, payload.Data.Total)
	for _, shipment := range payload.Data.Shipments {
		fmt.Println(shipment.TrackingCode)
	}
}
java
// Java 17+ — java.net.http, no dependencies (parse with Jackson/Gson)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class ShipOsOrder {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/orders/19602"))
            .header("X-Client-Id", System.getenv("SHIPOS_CLIENT_ID"))
            .header("X-Client-Secret", System.getenv("SHIPOS_CLIENT_SECRET"))
            .header("Accept", "application/json")
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 200) {
            throw new RuntimeException("ShipOS error: " + response.body());
        }

        System.out.println(response.body()); // {"data":{...}}
    }
}
csharp
// .NET 8+ — System.Net.Http.Json
using System.Net.Http.Json;
using System.Text.Json;

using var http = new HttpClient
{
    BaseAddress = new Uri("https://app.shipos.co.il/api/v2/"),
};
http.DefaultRequestHeaders.Add("X-Client-Id",
    Environment.GetEnvironmentVariable("SHIPOS_CLIENT_ID"));
http.DefaultRequestHeaders.Add("X-Client-Secret",
    Environment.GetEnvironmentVariable("SHIPOS_CLIENT_SECRET"));

var payload = await http.GetFromJsonAsync<JsonDocument>("orders/19602")
    ?? throw new InvalidOperationException("Empty response");
var order = payload.RootElement.GetProperty("data");

Console.WriteLine($"{order.GetProperty("order_id").GetString()} " +
    $"{order.GetProperty("total").GetString()}");
foreach (var shipment in order.GetProperty("shipments").EnumerateArray())
{
    Console.WriteLine(shipment.GetProperty("tracking_code").GetString());
}
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/orders/19602")
request = Net::HTTP::Get.new(uri)
request["X-Client-Id"] = ENV.fetch("SHIPOS_CLIENT_ID")
request["X-Client-Secret"] = ENV.fetch("SHIPOS_CLIENT_SECRET")
request["Accept"] = "application/json"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

raise "ShipOS error: #{response.body}" unless response.is_a?(Net::HTTPSuccess)

order = JSON.parse(response.body).fetch("data")

puts "#{order["order_id"]} #{order["total"]}"
order["shipments"].each { |shipment| puts shipment["tracking_code"] }
rust
// [dependencies]
// reqwest = { version = "0.12", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
// serde_json = "1"
use serde_json::Value;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let payload: Value = reqwest::Client::new()
        .get("https://app.shipos.co.il/api/v2/orders/19602")
        .header("X-Client-Id", std::env::var("SHIPOS_CLIENT_ID")?)
        .header("X-Client-Secret", std::env::var("SHIPOS_CLIENT_SECRET")?)
        .header("Accept", "application/json")
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;

    let order = &payload["data"];
    println!("{} {}", order["order_id"], order["total"]);
    if let Some(shipments) = order["shipments"].as_array() {
        for shipment in shipments {
            println!("{}", shipment["tracking_code"]);
        }
    }
    Ok(())
}

Response 200

shipments is present here because the shipments relation is loaded. It is an array of shipment resources (see GET /orders/{order}/shipments for the shipment field reference).

json
{
  "data": {
    "id": 84213,
    "order_id": "19602",
    "number": "19602",
    "source": "woocommerce",
    "total": "245.00",
    "currency": "ILS",
    "billing": {
      "first_name": "Dana",
      "last_name": "Levi",
      "address_1": "Herzl 10",
      "city": "Tel Aviv",
      "email": "dana@example.com",
      "phone": "0521234567"
    },
    "shipping": {
      "first_name": "Dana",
      "last_name": "Levi",
      "address_1": "Herzl 10",
      "city": "Tel Aviv"
    },
    "shipments": [
      {
        "uuid": "9f1c2d34-5678-4abc-9012-3456789abcde",
        "tracking_code": "66747921",
        "service_type": "home",
        "status": {
          "code": "1",
          "description": "Delivered",
          "is_delivered": true
        },
        "is_active": true
      }
    ],
    "created_at": "2026-07-20T08:14:11.000000Z",
    "updated_at": "2026-07-20T08:15:02.000000Z"
  }
}

Order fields

FieldTypeDescription
idintegerInternal ShipOS order id.
order_idstringExternal (platform) order id — the value used in the URL.
numberstringHuman-facing order number as shown to the merchant/customer.
sourcestringPlatform the order came from (e.g. woocommerce, shopify, wix, api_v2).
totalstringOrder total.
currencystringISO currency code.
billingobjectBilling party as stored on the order (keys vary by platform).
shippingobjectShipping/recipient party as stored on the order (keys vary by platform).
shipmentsarrayShipments attached to the order. Present only on this single-order endpoint.
created_atstringISO 8601 timestamp.
updated_atstringISO 8601 timestamp.

Platform-linkage ids, internal ids, tax/discount breakdowns and payment/shipping methods are intentionally excluded from the v2 contract.

Errors

StatuscodeWhen
401unauthenticatedMissing or invalid client credentials.
403forbiddenLicense unusable (see License selection).
404not_foundNo order with that external id belongs to the selected license.

GET /orders/{order}/shipments

List the shipments attached to a single order. Auth: client credentials. License: required.

Parameters

Path

FieldTypeRequiredDescription
orderstringyesThe external (platform) order id (order_id). Must belong to the selected license.

Query

FieldTypeRequiredDescription
license_keystringnoA License key to narrow the lookup to one carrier account. Omitted, it spans every license you own.

Example request

bash
curl --location 'https://app.shipos.co.il/api/v2/orders/19602/shipments' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'
js
// Node.js 18+ / browsers — no dependencies
const orderId = '19602'

const response = await fetch(
  `https://app.shipos.co.il/api/v2/orders/${orderId}/shipments`,
  {
    headers: {
      'X-Client-Id': process.env.SHIPOS_CLIENT_ID,
      'X-Client-Secret': process.env.SHIPOS_CLIENT_SECRET,
      Accept: 'application/json',
    },
  },
)

if (!response.ok) {
  const { error } = await response.json()
  throw new Error(`${error.code}: ${error.message}`)
}

const { data: shipments } = await response.json()

for (const shipment of shipments) {
  console.log(shipment.tracking_code, shipment.service_type, shipment.status?.description)
}
php
<?php
// composer require guzzlehttp/guzzle

$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.shipos.co.il/api/v2/',
    'headers' => [
        'X-Client-Id' => getenv('SHIPOS_CLIENT_ID'),
        'X-Client-Secret' => getenv('SHIPOS_CLIENT_SECRET'),
        'Accept' => 'application/json',
    ],
]);

$shipments = json_decode(
    $client->get('orders/19602/shipments')->getBody()->getContents(),
    true,
)['data'];

foreach ($shipments as $shipment) {
    echo $shipment['tracking_code'], ' ', $shipment['service_type'], PHP_EOL;
}
php
<?php

use Illuminate\Support\Facades\Http;

$shipments = Http::withHeaders([
    'X-Client-Id' => config('services.shipos.client_id'),
    'X-Client-Secret' => config('services.shipos.client_secret'),
])
    ->acceptJson()
    ->get('https://app.shipos.co.il/api/v2/orders/19602/shipments')
    ->throw()
    ->json('data');

foreach ($shipments as $shipment) {
    logger()->info($shipment['tracking_code'].' '.$shipment['service_type']);
}
python
# pip install httpx
import os

import httpx

response = httpx.get(
    "https://app.shipos.co.il/api/v2/orders/19602/shipments",
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
)
response.raise_for_status()
shipments = response.json()["data"]

for shipment in shipments:
    print(shipment["tracking_code"], shipment["service_type"])
go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

type shipmentsResponse struct {
	Data []struct {
		TrackingCode string `json:"tracking_code"`
		ServiceType  string `json:"service_type"`
	} `json:"data"`
}

func main() {
	req, _ := http.NewRequest("GET",
		"https://app.shipos.co.il/api/v2/orders/19602/shipments", nil)
	req.Header.Set("X-Client-Id", os.Getenv("SHIPOS_CLIENT_ID"))
	req.Header.Set("X-Client-Secret", os.Getenv("SHIPOS_CLIENT_SECRET"))
	req.Header.Set("Accept", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	var payload shipmentsResponse
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	for _, shipment := range payload.Data {
		fmt.Println(shipment.TrackingCode, shipment.ServiceType)
	}
}
java
// Java 17+ — java.net.http, no dependencies (parse with Jackson/Gson)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class ShipOsOrderShipments {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/orders/19602/shipments"))
            .header("X-Client-Id", System.getenv("SHIPOS_CLIENT_ID"))
            .header("X-Client-Secret", System.getenv("SHIPOS_CLIENT_SECRET"))
            .header("Accept", "application/json")
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 200) {
            throw new RuntimeException("ShipOS error: " + response.body());
        }

        System.out.println(response.body()); // {"data":[...]}
    }
}
csharp
// .NET 8+ — System.Net.Http.Json
using System.Net.Http.Json;
using System.Text.Json;

using var http = new HttpClient
{
    BaseAddress = new Uri("https://app.shipos.co.il/api/v2/"),
};
http.DefaultRequestHeaders.Add("X-Client-Id",
    Environment.GetEnvironmentVariable("SHIPOS_CLIENT_ID"));
http.DefaultRequestHeaders.Add("X-Client-Secret",
    Environment.GetEnvironmentVariable("SHIPOS_CLIENT_SECRET"));

var payload = await http.GetFromJsonAsync<JsonDocument>("orders/19602/shipments")
    ?? throw new InvalidOperationException("Empty response");

foreach (var shipment in payload.RootElement.GetProperty("data").EnumerateArray())
{
    Console.WriteLine($"{shipment.GetProperty("tracking_code").GetString()} " +
        $"{shipment.GetProperty("service_type").GetString()}");
}
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/orders/19602/shipments")
request = Net::HTTP::Get.new(uri)
request["X-Client-Id"] = ENV.fetch("SHIPOS_CLIENT_ID")
request["X-Client-Secret"] = ENV.fetch("SHIPOS_CLIENT_SECRET")
request["Accept"] = "application/json"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

raise "ShipOS error: #{response.body}" unless response.is_a?(Net::HTTPSuccess)

JSON.parse(response.body).fetch("data").each do |shipment|
  puts "#{shipment["tracking_code"]} #{shipment["service_type"]}"
end
rust
// [dependencies]
// reqwest = { version = "0.12", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
// serde_json = "1"
use serde_json::Value;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let payload: Value = reqwest::Client::new()
        .get("https://app.shipos.co.il/api/v2/orders/19602/shipments")
        .header("X-Client-Id", std::env::var("SHIPOS_CLIENT_ID")?)
        .header("X-Client-Secret", std::env::var("SHIPOS_CLIENT_SECRET")?)
        .header("Accept", "application/json")
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;

    if let Some(shipments) = payload["data"].as_array() {
        for shipment in shipments {
            println!("{} {}", shipment["tracking_code"], shipment["service_type"]);
        }
    }
    Ok(())
}

Response 200

json
{
  "data": [
    {
      "uuid": "9f1c2d34-5678-4abc-9012-3456789abcde",
      "tracking_code": "66747921",
      "status": {
        "code": "1",
        "description": "Delivered",
        "is_delivered": true
      },
      "service_type": "home",
      "is_active": true,
      "recipient": {
        "name": "Dana Levi",
        "phone": "0521234567",
        "company": null,
        "address": {
          "street": "Herzl 10",
          "number": "10",
          "city": "Tel Aviv",
          "state": null,
          "zip": "6100000",
          "country": "IL"
        }
      },
      "pickup_point_id": null,
      "packages": 1,
      "cod": null,
      "order": {
        "id": "19602",
        "number": null
      },
      "references": {
        "external_id": null
      },
      "short_tracking_code": null,
      "label_generated": true,
      "collection_status": null,
      "collected_at": null,
      "ready_at": null,
      "created_at": "2026-07-20T08:15:02.000000Z",
      "updated_at": "2026-07-20T08:20:44.000000Z"
    }
  ]
}

Shipment fields

FieldTypeDescription
uuidstringPublic shipment id.
tracking_codestringCarrier tracking / shipping code.
carrierobjectCarrier { id, name }. Present only when the provider relation is loaded.
statusobject | null{ code, description, is_delivered } — keys with null values are dropped; whole block is null when there is no status.
service_typestringOne of the service types (home, pickup, exchange, return).
is_activebooleanWhether the shipment is active (not cancelled).
recipientobject{ name, phone, company, address{ street, number, city, state, zip, country } }.
pickup_point_idstring | nullSelected pickup point id, for pickup-point shipments.
packagesmixed | nullPackage count / package data captured at creation.
codobject | null{ amount } when cash-on-delivery, otherwise null.
orderobject{ id, number } — the external order id, and order number when the order relation is loaded.
referencesobject{ external_id } — caller-supplied external reference, when set.
short_tracking_codestring | nullShort tracking code (pickup-point flows).
label_generatedbooleanWhether a shipping label has been generated.
collection_statusstring | nullCollection lifecycle status.
collected_atstring | nullISO 8601 timestamp of collection.
ready_atstring | nullISO 8601 timestamp of ready-for-pickup.
created_atstringISO 8601 timestamp.
updated_atstringISO 8601 timestamp.

Raw carrier payloads, platform-sync flags and internal ids are intentionally excluded from the v2 contract.

Errors

StatuscodeWhen
401unauthenticatedMissing or invalid client credentials.
403forbiddenLicense unusable (see License selection).
404not_foundNo order with that external id belongs to the selected license.