אצוות (Batches)
אצוות הן יצירת משלוחים בכמות גדולה באופן אסינכרוני. אתם שולחים עד 2000 payloads של משלוחים בבקשה אחת; ה-API שומר אותם, מתזמן את העבודה על-פני workers מקביליים, ומחזיר מיד 202 Accepted עם אצווה שאפשר לבצע עליה polling. כל פריט נוצר דרך אותו נתיב מוגן cache+lock כמו POST /shipments בודד, כך שפריט פגום נכשל בפני עצמו במקום לדחות את כל האצווה.
כל ה-endpoints של אצוות תחומים לרישיון: בוחרים את חשבון חברת השילוח באמצעות license_key (ב-query ב-GET, בגוף בקריאת היצירה) = הערך של licenses.key. רישיון פעיל יחיד משמש כברירת מחדל; מספר רישיונות פעילים ללא license_key מחזיר 422; ללא רישיון / לא פעיל / פג תוקף / לא בבעלות מחזיר 403.
מחזור חיים
אצווה עוברת בין הסטטוסים הבאים:
| סטטוס | משמעות |
|---|---|
queued | נוצרה; משימות ה-chunk שוגרו, אף פריט טרם הוכרע. |
processing | לפחות פריט אחד הוכרע, אך לא כולם. |
completed | כל פריט הוכרע (כל אחד הוא created או failed). |
לכל פריט סטטוס משלו: pending (טרם עובד), created (המשלוח נוצר — ראו shipment_id), או failed (ראו error). בצעו polling ל-GET /batches/{uuid} לספירות מצטברות ול-GET /batches/{uuid}/items לתוצאות פר-פריט.
GET /batches
הצגת רשימת האצוות של הקורא, מהחדשה לישנה, כל אחת עם הפריטים שלה טעונים מראש (eager-loaded). עימוד מבוסס-cursor. אימות: client credentials. רישיון: חובה.
פרמטרים
Query
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
license_key | string | חובה* | ה-licenses.key הבוחר את חשבון חברת השילוח. אופציונלי כאשר לקורא יש בדיוק רישיון פעיל אחד. |
per_page | integer | לא | פריטים לעמוד. ברירת מחדל 25, מוגבל ל-100. |
דוגמת בקשה
curl --location 'https://app.shipos.co.il/api/v2/batches?license_key={license_key}&per_page=25' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'// Node.js 18+ / דפדפנים — ללא תלויות
const url = new URL('https://app.shipos.co.il/api/v2/batches')
url.searchParams.set('license_key', '{license_key}')
url.searchParams.set('per_page', '25')
const response = await fetch(url, {
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: batches } = await response.json()
for (const batch of batches) {
console.log(batch.id, batch.status, batch.summary.created, 'created')
}<?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('batches', [
'query' => ['license_key' => '{license_key}', 'per_page' => 25],
]);
$batches = json_decode($response->getBody()->getContents(), true)['data'];
foreach ($batches as $batch) {
echo $batch['id'], ' ', $batch['status'], ' ', $batch['summary']['created'], PHP_EOL;
}<?php
use Illuminate\Support\Facades\Http;
$batches = 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/batches', [
'license_key' => '{license_key}',
'per_page' => 25,
])
->throw()
->json('data');
foreach ($batches as $batch) {
logger()->info($batch['id'].' '.$batch['status'].' '.$batch['summary']['created']);
}# pip install httpx
import os
import httpx
response = httpx.get(
"https://app.shipos.co.il/api/v2/batches",
params={"license_key": "{license_key}", "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()
for batch in response.json()["data"]:
print(batch["id"], batch["status"], batch["summary"]["created"])package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type batchList struct {
Data []struct {
ID string `json:"id"`
Status string `json:"status"`
Summary struct {
Created int `json:"created"`
Failed int `json:"failed"`
} `json:"summary"`
} `json:"data"`
}
func main() {
req, _ := http.NewRequest("GET",
"https://app.shipos.co.il/api/v2/batches?license_key={license_key}&per_page=25", 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 list batchList
if err := json.NewDecoder(res.Body).Decode(&list); err != nil {
panic(err)
}
for _, batch := range list.Data {
fmt.Println(batch.ID, batch.Status, batch.Summary.Created, batch.Summary.Failed)
}
}// Java 17+ — java.net.http, ללא תלויות (פענוח עם Jackson/Gson)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ShipOsListBatches {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/batches"
+ "?license_key={license_key}&per_page=25"))
.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":[...]} — מפו עם Jackson/Gson
}
}// .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>(
"batches?license_key={license_key}&per_page=25")
?? throw new InvalidOperationException("Empty response");
foreach (var batch in payload.RootElement.GetProperty("data").EnumerateArray())
{
Console.WriteLine($"{batch.GetProperty("id").GetString()} " +
$"{batch.GetProperty("status").GetString()}");
}require "net/http"
require "json"
uri = URI("https://app.shipos.co.il/api/v2/batches")
uri.query = URI.encode_www_form(license_key: "{license_key}", 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)
JSON.parse(response.body).fetch("data").each do |batch|
puts "#{batch["id"]} #{batch["status"]} #{batch.dig("summary", "created")}"
end// [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/batches")
.query(&[("license_key", "{license_key}"), ("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?;
for batch in payload["data"].as_array().unwrap_or(&Vec::new()) {
println!("{} {} {}", batch["id"], batch["status"], batch["summary"]["created"]);
}
Ok(())
}תשובה 200
כל אצווה כוללת את מערך ה-items שלה (נוכח רק ב-endpoint האינדקס הזה, שבו הרלציה נטענת מראש). ראו את מבנה הפריט תחת GET /batches/{uuid}/items.
{
"data": [
{
"id": "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55",
"status": "completed",
"summary": {
"total": 2,
"created": 1,
"failed": 1,
"pending": 0
},
"items": [
{
"id": 4101,
"position": 0,
"status": "created",
"shipment_id": "b7d3a1e0-9f2c-4a8b-8e11-6c5d4b3a2f10",
"payload": { "...": "הגוף שנשלח עבור הפריט" },
"error": null,
"created_at": "2026-07-29T08:00:00.000000Z",
"updated_at": "2026-07-29T08:00:04.000000Z"
}
],
"created_at": "2026-07-29T08:00:00.000000Z",
"updated_at": "2026-07-29T08:00:06.000000Z"
}
],
"links": { "...": "קישורי עימוד cursor" },
"meta": { "...": "מטא-נתוני עימוד cursor" }
}שגיאות
| סטטוס | קוד | מתי |
|---|---|---|
| 403 | forbidden | אין רישיון שמיש (לא פעיל / פג תוקף / לא בבעלות). |
| 422 | validation_failed | מספר רישיונות פעילים וללא license_key. |
POST /batches
תזמון אצוות יצירת משלוחים אסינכרונית. אימות: client credentials. רישיון: חובה.
מחזיר 202 Accepted — המשלוחים עדיין לא נוצרו. בצעו polling על ה-id של האצווה שהוחזר.
פרמטרים
Body
הבקשה מקבלת כל אחד משני מבני המעטפת, שניהם שקולים:
{ "shipments": [ <item>, <item>, ... ] }, או- מערך JSON חשוף ברמה העליונה
[ <item>, <item>, ... ](מנורמל תחתshipments).
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
shipments | array | כן | 1 עד 2000 payloads של משלוחים. |
license_key | string | חובה* | רישיון ברירת המחדל לכל פריט. שדה בגוף. אופציונלי כאשר לקורא יש בדיוק רישיון פעיל אחד. |
כל פריט (shipments[]) הוא גוף משלוח מלא — אותו payload שמתקבל ב-POST /shipments — ומאומת פר-פריט במהלך העיבוד (פריטים לא תקינים הופכים ל-failed, הם אינם דוחים את האצווה). בנוסף:
| שדה פריט | סוג | חובה | תיאור |
|---|---|---|---|
license_key | string | לא | דריסה פר-פריט הבוחרת רישיון אחר (חייב להשתייך לאותו לקוח, אחרת הפריט נכשל עם forbidden). נופל חזרה לרישיון ברירת המחדל של האצווה כשהוא מושמט. |
דוגמת בקשה
curl --location 'https://app.shipos.co.il/api/v2/batches' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"license_key": "{license_key}",
"shipments": [
{ "ship_data": { "...": "shipment fields" }, "order": { "...": "order fields" } },
{ "ship_data": { "...": "shipment fields" }, "order": { "...": "order fields" }, "license_key": "{other_license_key}" }
]
}'// Node.js 18+ / דפדפנים — ללא תלויות
const item = {
ship_data: { /* shipment fields — same as POST /shipments */ },
order: { /* order fields */ },
}
const response = await fetch('https://app.shipos.co.il/api/v2/batches', {
method: 'POST',
headers: {
'X-Client-Id': process.env.SHIPOS_CLIENT_ID,
'X-Client-Secret': process.env.SHIPOS_CLIENT_SECRET,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
license_key: '{license_key}',
shipments: [item, { ...item, license_key: '{other_license_key}' }],
}),
})
if (!response.ok) {
const { error } = await response.json()
throw new Error(`${error.code}: ${error.message}`)
}
const { data: batch } = await response.json() // 202 Accepted
console.log(batch.id, batch.status, batch.summary.pending)<?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',
],
]);
// כל פריט הוא גוף מלא של POST /shipments.
$item = ['ship_data' => [/* shipment fields */], 'order' => [/* order fields */]];
$response = $client->post('batches', [
'json' => [
'license_key' => '{license_key}',
'shipments' => [
$item,
$item + ['license_key' => '{other_license_key}'],
],
],
]);
$batch = json_decode($response->getBody()->getContents(), true)['data'];
echo $batch['id'], ' ', $batch['status'], ' pending: ', $batch['summary']['pending'], PHP_EOL;<?php
use Illuminate\Support\Facades\Http;
// כל פריט הוא גוף מלא של POST /shipments.
$item = ['ship_data' => [/* shipment fields */], 'order' => [/* order fields */]];
$batch = Http::withHeaders([
'X-Client-Id' => config('services.shipos.client_id'),
'X-Client-Secret' => config('services.shipos.client_secret'),
])
->acceptJson()
->post('https://app.shipos.co.il/api/v2/batches', [
'license_key' => '{license_key}',
'shipments' => [$item, $item + ['license_key' => '{other_license_key}']],
])
->throw()
->json('data');
logger()->info("batch {$batch['id']} is {$batch['status']}");# pip install httpx
import os
import httpx
item = {"ship_data": {}, "order": {}} # גוף מלא של POST /shipments
response = httpx.post(
"https://app.shipos.co.il/api/v2/batches",
headers={
"X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
"X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
"Accept": "application/json",
},
json={
"license_key": "{license_key}",
"shipments": [item, {**item, "license_key": "{other_license_key}"}],
},
)
response.raise_for_status()
batch = response.json()["data"] # 202 Accepted
print(batch["id"], batch["status"], batch["summary"]["pending"])package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
func main() {
// כל פריט הוא גוף מלא של POST /shipments.
item := map[string]any{"ship_data": map[string]any{}, "order": map[string]any{}}
override := map[string]any{"ship_data": map[string]any{}, "order": map[string]any{},
"license_key": "{other_license_key}"}
body, _ := json.Marshal(map[string]any{
"license_key": "{license_key}",
"shipments": []any{item, override},
})
req, _ := http.NewRequest("POST", "https://app.shipos.co.il/api/v2/batches",
bytes.NewReader(body))
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")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.StatusCode, string(out)) // 202 {"data":{"status":"queued",...}}
}// Java 17+ — java.net.http, ללא תלויות (בניית JSON עם Jackson/Gson)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ShipOsCreateBatch {
public static void main(String[] args) throws Exception {
// כל פריט הוא גוף מלא של POST /shipments.
String body = """
{
"license_key": "{license_key}",
"shipments": [
{"ship_data": {}, "order": {}},
{"ship_data": {}, "order": {}, "license_key": "{other_license_key}"}
]
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/batches"))
.header("X-Client-Id", System.getenv("SHIPOS_CLIENT_ID"))
.header("X-Client-Secret", System.getenv("SHIPOS_CLIENT_SECRET"))
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 202) {
throw new RuntimeException("ShipOS error: " + response.body());
}
System.out.println(response.body()); // {"data":{"status":"queued",...}}
}
}// .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"));
// כל פריט הוא גוף מלא של POST /shipments.
var response = await http.PostAsJsonAsync("batches", new
{
license_key = "{license_key}",
shipments = new object[]
{
new { ship_data = new { }, order = new { } },
new { ship_data = new { }, order = new { }, license_key = "{other_license_key}" },
},
});
response.EnsureSuccessStatusCode(); // 202 Accepted
var payload = await response.Content.ReadFromJsonAsync<JsonDocument>()
?? throw new InvalidOperationException("Empty response");
var batch = payload.RootElement.GetProperty("data");
Console.WriteLine($"{batch.GetProperty("id").GetString()} " +
$"{batch.GetProperty("status").GetString()}");require "net/http"
require "json"
item = { ship_data: {}, order: {} } # גוף מלא של POST /shipments
uri = URI("https://app.shipos.co.il/api/v2/batches")
request = Net::HTTP::Post.new(uri)
request["X-Client-Id"] = ENV.fetch("SHIPOS_CLIENT_ID")
request["X-Client-Secret"] = ENV.fetch("SHIPOS_CLIENT_SECRET")
request["Accept"] = "application/json"
request["Content-Type"] = "application/json"
request.body = JSON.dump({
license_key: "{license_key}",
shipments: [item, item.merge(license_key: "{other_license_key}")],
})
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)
batch = JSON.parse(response.body).fetch("data") # 202 Accepted
puts "#{batch["id"]} #{batch["status"]} #{batch.dig("summary", "pending")}"// [dependencies]
// reqwest = { version = "0.12", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
// serde_json = "1"
use serde_json::{json, Value};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let item = json!({ "ship_data": {}, "order": {} }); // גוף מלא של POST /shipments
let payload: Value = reqwest::Client::new()
.post("https://app.shipos.co.il/api/v2/batches")
.header("X-Client-Id", std::env::var("SHIPOS_CLIENT_ID")?)
.header("X-Client-Secret", std::env::var("SHIPOS_CLIENT_SECRET")?)
.header("Accept", "application/json")
.json(&json!({
"license_key": "{license_key}",
"shipments": [
item,
{ "ship_data": {}, "order": {}, "license_key": "{other_license_key}" }
],
}))
.send()
.await?
.error_for_status()?
.json()
.await?;
let batch = &payload["data"];
println!("{} {}", batch["id"], batch["status"]);
Ok(())
}תשובה 202
{
"data": {
"id": "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55",
"status": "queued",
"summary": {
"total": 2,
"created": 0,
"failed": 0,
"pending": 2
},
"created_at": "2026-07-29T08:00:00.000000Z",
"updated_at": "2026-07-29T08:00:00.000000Z"
}
}items מושמט כאן (הרלציה נטענת מראש רק ב-endpoint האינדקס).
שגיאות
| סטטוס | קוד | מתי |
|---|---|---|
| 403 | forbidden | אין רישיון שמיש (לא פעיל / פג תוקף / לא בבעלות). |
| 422 | validation_failed | shipments חסר/ריק, יותר מ-2000 פריטים, או מספר רישיונות פעילים וללא license_key. |
GET /batches/
החזרת אצווה בודדת בבעלות הרישיון של הקורא — ה-endpoint הראשי ל-polling של התקדמות מצטברת. אימות: client credentials. רישיון: חובה.
פרמטרים
Path
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
uuid | string | כן | ה-id של האצווה (UUID) שהוחזר ביצירה. |
Query
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
license_key | string | חובה* | בוחר את חשבון חברת השילוח. אופציונלי עם רישיון פעיל יחיד. |
דוגמת בקשה
curl --location 'https://app.shipos.co.il/api/v2/batches/9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55?license_key={license_key}' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'// Node.js 18+ / דפדפנים — ללא תלויות
const batchId = '9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55'
const url = new URL(`https://app.shipos.co.il/api/v2/batches/${batchId}`)
url.searchParams.set('license_key', '{license_key}')
const response = await fetch(url, {
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: batch } = await response.json()
// בצעו polling עד ש-batch.status === 'completed'.
console.log(batch.status, batch.summary.created, batch.summary.pending)<?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',
],
]);
$batchId = '9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55';
$response = $client->get("batches/{$batchId}", [
'query' => ['license_key' => '{license_key}'],
]);
$batch = json_decode($response->getBody()->getContents(), true)['data'];
// בצעו polling עד ש-$batch['status'] === 'completed'.
echo $batch['status'], ' ', $batch['summary']['created'], '/', $batch['summary']['total'], PHP_EOL;<?php
use Illuminate\Support\Facades\Http;
$batchId = '9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55';
$batch = 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/batches/{$batchId}", [
'license_key' => '{license_key}',
])
->throw()
->json('data');
// בצעו polling עד ש-$batch['status'] === 'completed'.
logger()->info($batch['status'], $batch['summary']);# pip install httpx
import os
import httpx
batch_id = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55"
response = httpx.get(
f"https://app.shipos.co.il/api/v2/batches/{batch_id}",
params={"license_key": "{license_key}"},
headers={
"X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
"X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
"Accept": "application/json",
},
)
response.raise_for_status()
batch = response.json()["data"]
# בצעו polling עד ש-batch["status"] == "completed".
print(batch["status"], batch["summary"])package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type batchResponse struct {
Data struct {
ID string `json:"id"`
Status string `json:"status"`
Summary struct {
Total int `json:"total"`
Created int `json:"created"`
Failed int `json:"failed"`
Pending int `json:"pending"`
} `json:"summary"`
} `json:"data"`
}
func main() {
batchID := "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55"
req, _ := http.NewRequest("GET",
"https://app.shipos.co.il/api/v2/batches/"+batchID+"?license_key={license_key}", 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 batch batchResponse
if err := json.NewDecoder(res.Body).Decode(&batch); err != nil {
panic(err)
}
// בצעו polling עד ש-batch.Data.Status == "completed".
fmt.Println(batch.Data.Status, batch.Data.Summary.Created, batch.Data.Summary.Pending)
}// Java 17+ — java.net.http, ללא תלויות (פענוח עם Jackson/Gson)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ShipOsShowBatch {
public static void main(String[] args) throws Exception {
String batchId = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/batches/" + batchId
+ "?license_key={license_key}"))
.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());
}
// בצעו polling עד ש-data.status הוא "completed".
System.out.println(response.body()); // {"data":{...}} — מפו עם Jackson/Gson
}
}// .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 batchId = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55";
var payload = await http.GetFromJsonAsync<JsonDocument>(
$"batches/{batchId}?license_key={{license_key}}")
?? throw new InvalidOperationException("Empty response");
var batch = payload.RootElement.GetProperty("data");
// בצעו polling עד ש-status הוא "completed".
Console.WriteLine($"{batch.GetProperty("status").GetString()} " +
$"{batch.GetProperty("summary").GetProperty("pending").GetInt32()} pending");require "net/http"
require "json"
batch_id = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55"
uri = URI("https://app.shipos.co.il/api/v2/batches/#{batch_id}")
uri.query = URI.encode_www_form(license_key: "{license_key}")
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)
batch = JSON.parse(response.body).fetch("data")
# בצעו polling עד ש-batch["status"] == "completed".
puts "#{batch["status"]} #{batch["summary"]}"// [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 batch_id = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55";
let payload: Value = reqwest::Client::new()
.get(format!("https://app.shipos.co.il/api/v2/batches/{batch_id}"))
.query(&[("license_key", "{license_key}")])
.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 batch = &payload["data"];
// בצעו polling עד ש-batch["status"] == "completed".
println!("{} {}", batch["status"], batch["summary"]);
Ok(())
}תשובה 200
{
"data": {
"id": "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55",
"status": "processing",
"summary": {
"total": 2,
"created": 1,
"failed": 0,
"pending": 1
},
"created_at": "2026-07-29T08:00:00.000000Z",
"updated_at": "2026-07-29T08:00:04.000000Z"
}
}שדות התשובה
| שדה | סוג | תיאור |
|---|---|---|
id | string | ה-UUID של האצווה. |
status | string | queued, processing או completed. |
summary.total | integer | סך הפריטים שנשלחו. |
summary.created | integer | פריטים שהניבו משלוח. |
summary.failed | integer | פריטים שנכשלו. |
summary.pending | integer | פריטים שטרם הוכרעו (total - created - failed, לא פחות מ-0). |
items | array | נוכח רק ב-endpoint האינדקס; מושמט כאן. |
created_at / updated_at | string | חותמות זמן ISO-8601. |
שגיאות
| סטטוס | קוד | מתי |
|---|---|---|
| 403 | forbidden | אין רישיון שמיש. |
| 404 | not_found | אף אצווה עם ה-UUID הזה אינה שייכת לרישיון של הקורא (Batch not found.). |
| 422 | validation_failed | מספר רישיונות פעילים וללא license_key. |
GET /batches/{uuid}/items
החזרת התוצאות פר-פריט של אצווה, עם עימוד. אימות: client credentials. רישיון: חובה.
פרמטרים
Path
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
uuid | string | כן | ה-id של האצווה (UUID). |
Query
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
license_key | string | חובה* | בוחר את חשבון חברת השילוח. אופציונלי עם רישיון פעיל יחיד. |
per_page | integer | לא | פריטים לעמוד. ברירת מחדל 50, מוגבל ל-100. |
דוגמת בקשה
curl --location 'https://app.shipos.co.il/api/v2/batches/9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55/items?license_key={license_key}&per_page=50' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'// Node.js 18+ / דפדפנים — ללא תלויות
const batchId = '9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55'
const url = new URL(`https://app.shipos.co.il/api/v2/batches/${batchId}/items`)
url.searchParams.set('license_key', '{license_key}')
url.searchParams.set('per_page', '50')
const response = await fetch(url, {
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: items } = await response.json()
for (const item of items) {
console.log(item.position, item.status, item.shipment_id ?? item.error?.code)
}<?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',
],
]);
$batchId = '9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55';
$response = $client->get("batches/{$batchId}/items", [
'query' => ['license_key' => '{license_key}', 'per_page' => 50],
]);
$items = json_decode($response->getBody()->getContents(), true)['data'];
foreach ($items as $item) {
echo $item['position'], ' ', $item['status'], ' ',
$item['shipment_id'] ?? ($item['error']['code'] ?? ''), PHP_EOL;
}<?php
use Illuminate\Support\Facades\Http;
$batchId = '9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55';
$items = 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/batches/{$batchId}/items", [
'license_key' => '{license_key}',
'per_page' => 50,
])
->throw()
->json('data');
foreach ($items as $item) {
logger()->info($item['position'].' '.$item['status'], ['error' => $item['error']]);
}# pip install httpx
import os
import httpx
batch_id = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55"
response = httpx.get(
f"https://app.shipos.co.il/api/v2/batches/{batch_id}/items",
params={"license_key": "{license_key}", "per_page": 50},
headers={
"X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
"X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
"Accept": "application/json",
},
)
response.raise_for_status()
for item in response.json()["data"]:
print(item["position"], item["status"], item["shipment_id"] or item["error"])package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type itemList struct {
Data []struct {
Position int `json:"position"`
Status string `json:"status"`
ShipmentID *string `json:"shipment_id"`
Error json.RawMessage `json:"error"`
} `json:"data"`
}
func main() {
batchID := "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55"
req, _ := http.NewRequest("GET",
"https://app.shipos.co.il/api/v2/batches/"+batchID+
"/items?license_key={license_key}&per_page=50", 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 list itemList
if err := json.NewDecoder(res.Body).Decode(&list); err != nil {
panic(err)
}
for _, item := range list.Data {
fmt.Println(item.Position, item.Status, string(item.Error))
}
}// Java 17+ — java.net.http, ללא תלויות (פענוח עם Jackson/Gson)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ShipOsBatchItems {
public static void main(String[] args) throws Exception {
String batchId = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/batches/" + batchId
+ "/items?license_key={license_key}&per_page=50"))
.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":[...]} — מפו עם Jackson/Gson
}
}// .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 batchId = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55";
var payload = await http.GetFromJsonAsync<JsonDocument>(
$"batches/{batchId}/items?license_key={{license_key}}&per_page=50")
?? throw new InvalidOperationException("Empty response");
foreach (var item in payload.RootElement.GetProperty("data").EnumerateArray())
{
Console.WriteLine($"{item.GetProperty("position").GetInt32()} " +
$"{item.GetProperty("status").GetString()} {item.GetProperty("error")}");
}require "net/http"
require "json"
batch_id = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55"
uri = URI("https://app.shipos.co.il/api/v2/batches/#{batch_id}/items")
uri.query = URI.encode_www_form(license_key: "{license_key}", per_page: 50)
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 |item|
puts "#{item["position"]} #{item["status"]} #{item["shipment_id"] || item["error"]}"
end// [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 batch_id = "9b1f7c2e-3a4d-4f18-9c7a-2b6e1d0f8a55";
let payload: Value = reqwest::Client::new()
.get(format!("https://app.shipos.co.il/api/v2/batches/{batch_id}/items"))
.query(&[("license_key", "{license_key}"), ("per_page", "50")])
.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?;
for item in payload["data"].as_array().unwrap_or(&Vec::new()) {
println!("{} {} {}", item["position"], item["status"], item["error"]);
}
Ok(())
}תשובה 200
{
"data": [
{
"id": 4101,
"position": 0,
"status": "created",
"shipment_id": "b7d3a1e0-9f2c-4a8b-8e11-6c5d4b3a2f10",
"payload": { "...": "הגוף שנשלח עבור הפריט" },
"error": null,
"created_at": "2026-07-29T08:00:00.000000Z",
"updated_at": "2026-07-29T08:00:04.000000Z"
},
{
"id": 4102,
"position": 1,
"status": "failed",
"shipment_id": null,
"payload": { "...": "הגוף שנשלח עבור הפריט" },
"error": {
"code": "validation_failed",
"ship_data.city": ["The ship_data.city field is required."]
},
"created_at": "2026-07-29T08:00:00.000000Z",
"updated_at": "2026-07-29T08:00:05.000000Z"
}
],
"links": { "...": "קישורי עימוד cursor" },
"meta": { "...": "מטא-נתוני עימוד cursor" }
}שדות התשובה (פר פריט)
| שדה | סוג | תיאור |
|---|---|---|
id | integer | מזהה פריט האצווה. |
position | integer | אינדקס מבוסס-אפס בתוך האצווה שנשלחה. |
status | string | pending, created או failed. |
shipment_id | string | null | ה-UUID של המשלוח שנוצר כאשר status הוא created; אחרת null. |
payload | object | הגוף המדויק שנשלח עבור הפריט. |
error | object | null | פירוט הכשל כאשר status הוא failed: תמיד code (למשל validation_failed, forbidden, carrier_error, server_error) בתוספת message ו/או שגיאות ברמת השדה. אחרת null. |
created_at / updated_at | string | חותמות זמן ISO-8601. |
שגיאות
| סטטוס | קוד | מתי |
|---|---|---|
| 403 | forbidden | אין רישיון שמיש. |
| 404 | not_found | אף אצווה עם ה-UUID הזה אינה שייכת לרישיון של הקורא (Batch not found.). |
| 422 | validation_failed | מספר רישיונות פעילים וללא license_key. |