יצירת המשלוח הראשון שלכם
המדריך הזה מוביל אתכם מסט חדש של פרטי גישה ל-API ועד משלוח שנוצר, עם תווית מוכנה להדפסה ומעקב חי. הוא עובר מקצה לקצה על ארבעת ה-endpoints המרכזיים — חשבון, רישיונות, משלוחים ומעקב.
לפני שמתחילים
תצטרכו את פרטי הלקוח (client credentials) של ה-API — צמד client_id ו-client_secret. כל בקשה מאומתת שולחת אותם ככותרות (headers):
X-Client-Id: {client_id}
X-Client-Secret: {client_secret}
Accept: application/jsonבקשות עם גוף (body) שולחות גם Content-Type: application/json. כל הדוגמאות משתמשות בכתובת הבסיס https://app.shipos.co.il/api/v2. לפרטים ראו את מדריך האימות.
שלב 1 — אימות פרטי הגישה
קראו ל-GET /account. הקריאה מחזירה את חשבון הסוחר שמאחורי פרטי הגישה שלכם, עם כל חשבונות המובילים (הרישיונות) מוטמעים בתשובה — תגובה מוצלחת מוכיחה שהכותרות שלכם תקינות.
curl --location 'https://app.shipos.co.il/api/v2/account' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch('https://app.shipos.co.il/api/v2/account', {
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: account } = await response.json()
console.log(account.company_name, '—', account.licenses.length, 'license(s)')<?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',
],
]);
$account = json_decode(
$client->get('account')->getBody()->getContents(),
true,
)['data'];
echo $account['company_name'], ' — ', count($account['licenses']), ' license(s)', PHP_EOL;<?php
use Illuminate\Support\Facades\Http;
$account = 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/account')
->throw()
->json('data');
logger()->info($account['company_name'], ['licenses' => count($account['licenses'])]);# pip install httpx
import os
import httpx
response = httpx.get(
"https://app.shipos.co.il/api/v2/account",
headers={
"X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
"X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
"Accept": "application/json",
},
)
response.raise_for_status()
account = response.json()["data"]
print(account["company_name"], "—", len(account["licenses"]), "license(s)")package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type accountResponse struct {
Data struct {
CompanyName string `json:"company_name"`
Licenses []json.RawMessage `json:"licenses"`
} `json:"data"`
}
func main() {
req, _ := http.NewRequest("GET", "https://app.shipos.co.il/api/v2/account", 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 account accountResponse
if err := json.NewDecoder(res.Body).Decode(&account); err != nil {
panic(err)
}
fmt.Println(account.Data.CompanyName, "—", len(account.Data.Licenses), "license(s)")
}// 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 VerifyCredentials {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/account"))
.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>("account")
?? throw new InvalidOperationException("Empty response");
var account = payload.RootElement.GetProperty("data");
Console.WriteLine($"{account.GetProperty("company_name").GetString()} — " +
$"{account.GetProperty("licenses").GetArrayLength()} license(s)");require "net/http"
require "json"
uri = URI("https://app.shipos.co.il/api/v2/account")
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)
account = JSON.parse(response.body).fetch("data")
puts "#{account["company_name"]} — #{account["licenses"].size} license(s)"// [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/account")
.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 account = &payload["data"];
let licenses = account["licenses"].as_array().map_or(0, Vec::len);
println!("{} — {} license(s)", account["company_name"], licenses);
Ok(())
}תגובת 200 חוזרת עם מעטפת { "data": ... } הסטנדרטית:
{
"data": {
"id": 1042,
"name": "ישראל ישראלי",
"email": "israel@example.co.il",
"phone": "0521234567",
"locale": "he",
"company_name": "אופנת הרצל בע״מ",
"enable_api": 1,
"can_use_collection_points": true,
"label_method": "A4",
"label_type": null,
"licenses": [ ... ]
}
}אם קיבלתם 401 במקום — פרטי הגישה שגויים או חסרים; ראו שגיאות.
שלב 2 — איתור ה-license_key שלכם
כל משלוח נוצר תחת רישיון אחד (חשבון מוביל). endpoints של כתיבה בוחרים אותו באמצעות השדה license_key בגוף הבקשה; endpoints מסוג GET משתמשים בפרמטר שאילתה license_key. הערך הוא השדה key שמוחזר מ-GET /licenses:
curl --location 'https://app.shipos.co.il/api/v2/licenses' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch('https://app.shipos.co.il/api/v2/licenses', {
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: licenses } = await response.json()
for (const license of licenses) {
console.log(license.key, '→', license.company.carrier.name, license.is_active)
}<?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',
],
]);
$licenses = json_decode(
$client->get('licenses')->getBody()->getContents(),
true,
)['data'];
foreach ($licenses as $license) {
echo $license['key'], ' → ', $license['company']['carrier']['name'], PHP_EOL;
}<?php
use Illuminate\Support\Facades\Http;
$licenses = 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/licenses')
->throw()
->json('data');
foreach ($licenses as $license) {
logger()->info($license['key'].' → '.$license['company']['carrier']['name']);
}# pip install httpx
import os
import httpx
response = httpx.get(
"https://app.shipos.co.il/api/v2/licenses",
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 lic in response.json()["data"]:
print(lic["key"], "→", lic["company"]["carrier"]["name"], lic["is_active"])package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type licensesResponse struct {
Data []struct {
Key string `json:"key"`
IsActive bool `json:"is_active"`
Company struct {
Carrier struct {
Name string `json:"name"`
} `json:"carrier"`
} `json:"company"`
} `json:"data"`
}
func main() {
req, _ := http.NewRequest("GET", "https://app.shipos.co.il/api/v2/licenses", 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 licensesResponse
if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
panic(err)
}
for _, license := range payload.Data {
fmt.Println(license.Key, "→", license.Company.Carrier.Name, license.IsActive)
}
}// 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 ListLicenses {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/licenses"))
.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":[{"key":"a1b2c3d4e5f6",...}]}
}
}// .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>("licenses")
?? throw new InvalidOperationException("Empty response");
foreach (var license in payload.RootElement.GetProperty("data").EnumerateArray())
{
var carrier = license.GetProperty("company").GetProperty("carrier");
Console.WriteLine(
$"{license.GetProperty("key").GetString()} → {carrier.GetProperty("name").GetString()}");
}require "net/http"
require "json"
uri = URI("https://app.shipos.co.il/api/v2/licenses")
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 |license|
puts "#{license["key"]} → #{license.dig("company", "carrier", "name")}"
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/licenses")
.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(licenses) = payload["data"].as_array() {
for license in licenses {
println!(
"{} → {}",
license["key"], license["company"]["carrier"]["name"]
);
}
}
Ok(())
}{
"data": [
{
"id": 812,
"key": "a1b2c3d4e5f6", // ← זהו ה-license_key שלכם
"name": "חשבון HFD ראשי",
"company": {
"id": 3391,
"name": "בלדר לוגיסטיקה בע״מ",
"carrier": { "id": 4, "name": "HFD" }
},
"commitment_day": 3,
"multiple_shipment": true,
"is_active": true,
"is_expired": false,
"expires_at": "2027-01-31T00:00:00.000000Z",
"settings": [ ... ]
}
]
}מתי אפשר להשמיט את license_key?
אם לחשבון שלכם יש בדיוק רישיון פעיל אחד, הוא משמש כברירת מחדל ואפשר להשמיט את license_key. עם יותר מרישיון פעיל אחד, השמטה מחזירה 422; מפתח לא פעיל, שפג תוקפו או שאינו בבעלותכם מחזיר 403. הכללים המלאים ברישיונות ו-license_key.
שלב 3 — יצירת המשלוח
POST /shipments מקבל מעטפת {ship_data, order}:
ship_data— המטען שמופנה למוביל: למי לשלוח, לאן ואיך. השדותcontact_name,contact_phone,type,returnו-packagesהם חובה;streetו-cityהם חובה אלא אם הגדרתםship_data.pickup(משלוח לנקודת איסוף).order— תמונת ההזמנה שנשמרת לצד המשלוח, כולל בלוק נמעןorder.shipping(חובה) ו-order_itemsאופציונליים.
עבור ship_data.type, 1 = משלוח רגיל ו-2 = איסוף (החזרה); עבור ship_data.return, 1 = כיוון אחד ו-2 = הלוך ושוב. למשלוח רגיל עד הבית השתמשו ב-type: "1", return: "1".
שלחו כותרת Idempotency-Key — כל מחרוזת ייחודית לכל משלוח לוגי (UUID עובד מצוין). אם הבקשה מסתיימת ב-timeout או שהתהליך שלכם קורס, ניסיון חוזר עם אותו מפתח מחזיר בבטחה את המשלוח שכבר נוצר, במקום ליצור (ולשלם על) כפילות. ראו אידמפוטנטיות.
curl --location 'https://app.shipos.co.il/api/v2/shipments' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f' \
--data '{
"license_key": "a1b2c3d4e5f6",
"ship_data": {
"contact_name": "ישראל ישראלי",
"contact_phone": "0521234567",
"contact_mail": "israel@example.co.il",
"street": "הרצל",
"number": "10",
"city": "תל אביב",
"entrance": "ב",
"floor": "3",
"apartment": "12",
"type": "1",
"return": "1",
"packages": 1,
"note": "להשאיר אצל השומר אם אין איש בבית"
},
"order": {
"id": "1042",
"number": "1042",
"status": "processing",
"currency": "ILS",
"total": 249.90,
"source": "api",
"shipping": {
"first_name": "ישראל",
"last_name": "ישראלי",
"phone": "0521234567",
"email": "israel@example.co.il",
"address_1": "הרצל",
"address_2": "10",
"city": "תל אביב",
"postcode": "6688312",
"country": "IL"
},
"order_items": [
{
"sku": "TSHIRT-M-BLK",
"name": "חולצת טי כותנה (M, שחור)",
"quantity": 2,
"price": 89.95,
"total": 179.90
},
{
"sku": "SOCKS-3PK",
"name": "שלישיית גרביים",
"quantity": 1,
"price": 70.00,
"total": 70.00
}
]
}
}'// Node.js 18+ / דפדפנים — ללא תלויות
const res = await fetch('https://app.shipos.co.il/api/v2/shipments', {
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',
'Idempotency-Key': '4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f',
},
body: JSON.stringify({
license_key: 'a1b2c3d4e5f6',
ship_data: {
contact_name: 'ישראל ישראלי',
contact_phone: '0521234567',
contact_mail: 'israel@example.co.il',
street: 'הרצל',
number: '10',
city: 'תל אביב',
entrance: 'ב',
floor: '3',
apartment: '12',
type: '1',
return: '1',
packages: 1,
note: 'להשאיר אצל השומר אם אין איש בבית',
},
order: {
id: '1042',
number: '1042',
status: 'processing',
currency: 'ILS',
total: 249.9,
source: 'api',
shipping: {
first_name: 'ישראל',
last_name: 'ישראלי',
phone: '0521234567',
email: 'israel@example.co.il',
address_1: 'הרצל',
address_2: '10',
city: 'תל אביב',
postcode: '6688312',
country: 'IL',
},
order_items: [
{ sku: 'TSHIRT-M-BLK', name: 'חולצת טי כותנה (M, שחור)', quantity: 2, price: 89.95, total: 179.9 },
{ sku: 'SOCKS-3PK', name: 'שלישיית גרביים', quantity: 1, price: 70.0, total: 70.0 },
],
},
}),
})
const { data: shipment } = await res.json() // res.status === 201<?php
// composer require guzzlehttp/guzzle
$client = new \GuzzleHttp\Client(['base_uri' => 'https://app.shipos.co.il/api/v2/']);
$response = $client->post('shipments', [
'headers' => [
'X-Client-Id' => getenv('SHIPOS_CLIENT_ID'),
'X-Client-Secret' => getenv('SHIPOS_CLIENT_SECRET'),
'Accept' => 'application/json',
'Idempotency-Key' => '4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f',
],
'json' => [
'license_key' => 'a1b2c3d4e5f6',
'ship_data' => [
'contact_name' => 'ישראל ישראלי',
'contact_phone' => '0521234567',
'contact_mail' => 'israel@example.co.il',
'street' => 'הרצל',
'number' => '10',
'city' => 'תל אביב',
'entrance' => 'ב',
'floor' => '3',
'apartment' => '12',
'type' => '1',
'return' => '1',
'packages' => 1,
'note' => 'להשאיר אצל השומר אם אין איש בבית',
],
'order' => [
'id' => '1042',
'number' => '1042',
'status' => 'processing',
'currency' => 'ILS',
'total' => 249.90,
'source' => 'api',
'shipping' => [
'first_name' => 'ישראל',
'last_name' => 'ישראלי',
'phone' => '0521234567',
'email' => 'israel@example.co.il',
'address_1' => 'הרצל',
'address_2' => '10',
'city' => 'תל אביב',
'postcode' => '6688312',
'country' => 'IL',
],
'order_items' => [
['sku' => 'TSHIRT-M-BLK', 'name' => 'חולצת טי כותנה (M, שחור)', 'quantity' => 2, 'price' => 89.95, 'total' => 179.90],
['sku' => 'SOCKS-3PK', 'name' => 'שלישיית גרביים', 'quantity' => 1, 'price' => 70.00, 'total' => 70.00],
],
],
],
]);
$shipment = json_decode((string) $response->getBody(), true)['data'];<?php
use Illuminate\Support\Facades\Http;
$shipment = Http::withHeaders([
'X-Client-Id' => config('services.shipos.client_id'),
'X-Client-Secret' => config('services.shipos.client_secret'),
'Idempotency-Key' => '4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f',
])
->acceptJson()
->post('https://app.shipos.co.il/api/v2/shipments', [
'license_key' => 'a1b2c3d4e5f6',
'ship_data' => [
'contact_name' => 'ישראל ישראלי',
'contact_phone' => '0521234567',
'contact_mail' => 'israel@example.co.il',
'street' => 'הרצל',
'number' => '10',
'city' => 'תל אביב',
'entrance' => 'ב',
'floor' => '3',
'apartment' => '12',
'type' => '1',
'return' => '1',
'packages' => 1,
'note' => 'להשאיר אצל השומר אם אין איש בבית',
],
'order' => [
'id' => '1042',
'number' => '1042',
'status' => 'processing',
'currency' => 'ILS',
'total' => 249.90,
'source' => 'api',
'shipping' => [
'first_name' => 'ישראל',
'last_name' => 'ישראלי',
'phone' => '0521234567',
'email' => 'israel@example.co.il',
'address_1' => 'הרצל',
'address_2' => '10',
'city' => 'תל אביב',
'postcode' => '6688312',
'country' => 'IL',
],
'order_items' => [
['sku' => 'TSHIRT-M-BLK', 'name' => 'חולצת טי כותנה (M, שחור)', 'quantity' => 2, 'price' => 89.95, 'total' => 179.90],
['sku' => 'SOCKS-3PK', 'name' => 'שלישיית גרביים', 'quantity' => 1, 'price' => 70.00, 'total' => 70.00],
],
],
])
->throw()
->json('data');# pip install httpx
import os
import httpx
payload = {
"license_key": "a1b2c3d4e5f6",
"ship_data": {
"contact_name": "ישראל ישראלי",
"contact_phone": "0521234567",
"contact_mail": "israel@example.co.il",
"street": "הרצל",
"number": "10",
"city": "תל אביב",
"entrance": "ב",
"floor": "3",
"apartment": "12",
"type": "1",
"return": "1",
"packages": 1,
"note": "להשאיר אצל השומר אם אין איש בבית",
},
"order": {
"id": "1042",
"number": "1042",
"status": "processing",
"currency": "ILS",
"total": 249.90,
"source": "api",
"shipping": {
"first_name": "ישראל",
"last_name": "ישראלי",
"phone": "0521234567",
"email": "israel@example.co.il",
"address_1": "הרצל",
"address_2": "10",
"city": "תל אביב",
"postcode": "6688312",
"country": "IL",
},
"order_items": [
{"sku": "TSHIRT-M-BLK", "name": "חולצת טי כותנה (M, שחור)", "quantity": 2, "price": 89.95, "total": 179.90},
{"sku": "SOCKS-3PK", "name": "שלישיית גרביים", "quantity": 1, "price": 70.00, "total": 70.00},
],
},
}
response = httpx.post(
"https://app.shipos.co.il/api/v2/shipments",
json=payload,
headers={
"X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
"X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
"Accept": "application/json",
"Idempotency-Key": "4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f",
},
timeout=60.0,
)
response.raise_for_status() # 201
shipment = response.json()["data"]
print(shipment["uuid"], shipment["tracking_code"])package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
payload := map[string]any{
"license_key": "a1b2c3d4e5f6",
"ship_data": map[string]any{
"contact_name": "ישראל ישראלי",
"contact_phone": "0521234567",
"contact_mail": "israel@example.co.il",
"street": "הרצל",
"number": "10",
"city": "תל אביב",
"entrance": "ב",
"floor": "3",
"apartment": "12",
"type": "1",
"return": "1",
"packages": 1,
"note": "להשאיר אצל השומר אם אין איש בבית",
},
"order": map[string]any{
"id": "1042",
"number": "1042",
"status": "processing",
"currency": "ILS",
"total": 249.90,
"source": "api",
"shipping": map[string]any{
"first_name": "ישראל",
"last_name": "ישראלי",
"phone": "0521234567",
"email": "israel@example.co.il",
"address_1": "הרצל",
"address_2": "10",
"city": "תל אביב",
"postcode": "6688312",
"country": "IL",
},
"order_items": []map[string]any{
{"sku": "TSHIRT-M-BLK", "name": "חולצת טי כותנה (M, שחור)", "quantity": 2, "price": 89.95, "total": 179.90},
{"sku": "SOCKS-3PK", "name": "שלישיית גרביים", "quantity": 1, "price": 70.00, "total": 70.00},
},
},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://app.shipos.co.il/api/v2/shipments", 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")
req.Header.Set("Idempotency-Key", "4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var payloadOut struct {
Data struct {
UUID string `json:"uuid"`
TrackingCode string `json:"tracking_code"`
} `json:"data"`
}
if err := json.NewDecoder(res.Body).Decode(&payloadOut); err != nil {
panic(err)
}
fmt.Println(res.StatusCode, payloadOut.Data.UUID, payloadOut.Data.TrackingCode)
}// 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 CreateShipment {
public static void main(String[] args) throws Exception {
String body = """
{
"license_key": "a1b2c3d4e5f6",
"ship_data": {
"contact_name": "ישראל ישראלי",
"contact_phone": "0521234567",
"contact_mail": "israel@example.co.il",
"street": "הרצל",
"number": "10",
"city": "תל אביב",
"entrance": "ב",
"floor": "3",
"apartment": "12",
"type": "1",
"return": "1",
"packages": 1,
"note": "להשאיר אצל השומר אם אין איש בבית"
},
"order": {
"id": "1042",
"number": "1042",
"status": "processing",
"currency": "ILS",
"total": 249.90,
"source": "api",
"shipping": {
"first_name": "ישראל",
"last_name": "ישראלי",
"phone": "0521234567",
"email": "israel@example.co.il",
"address_1": "הרצל",
"address_2": "10",
"city": "תל אביב",
"postcode": "6688312",
"country": "IL"
},
"order_items": [
{"sku": "TSHIRT-M-BLK", "name": "חולצת טי כותנה (M, שחור)", "quantity": 2, "price": 89.95, "total": 179.90},
{"sku": "SOCKS-3PK", "name": "שלישיית גרביים", "quantity": 1, "price": 70.00, "total": 70.00}
]
}
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/shipments"))
.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")
.header("Idempotency-Key", "4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 201) {
throw new RuntimeException("ShipOS error: " + response.body());
}
System.out.println(response.body()); // {"data":{"uuid":...,"tracking_code":...}}
}
}// .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"));
http.DefaultRequestHeaders.Add("Idempotency-Key",
"4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f");
var payload = new
{
license_key = "a1b2c3d4e5f6",
ship_data = new
{
contact_name = "ישראל ישראלי",
contact_phone = "0521234567",
contact_mail = "israel@example.co.il",
street = "הרצל",
number = "10",
city = "תל אביב",
entrance = "ב",
floor = "3",
apartment = "12",
type = "1",
@return = "1", // עובר סריאליזציה כ-"return"
packages = 1,
note = "להשאיר אצל השומר אם אין איש בבית",
},
order = new
{
id = "1042",
number = "1042",
status = "processing",
currency = "ILS",
total = 249.90m,
source = "api",
shipping = new
{
first_name = "ישראל",
last_name = "ישראלי",
phone = "0521234567",
email = "israel@example.co.il",
address_1 = "הרצל",
address_2 = "10",
city = "תל אביב",
postcode = "6688312",
country = "IL",
},
order_items = new object[]
{
new { sku = "TSHIRT-M-BLK", name = "חולצת טי כותנה (M, שחור)", quantity = 2, price = 89.95m, total = 179.90m },
new { sku = "SOCKS-3PK", name = "שלישיית גרביים", quantity = 1, price = 70.00m, total = 70.00m },
},
},
};
var response = await http.PostAsJsonAsync("shipments", payload);
response.EnsureSuccessStatusCode(); // 201
var created = (await response.Content.ReadFromJsonAsync<JsonDocument>())!
.RootElement.GetProperty("data");
Console.WriteLine($"{created.GetProperty("uuid").GetString()} " +
$"{created.GetProperty("tracking_code").GetString()}");require "net/http"
require "json"
payload = {
license_key: "a1b2c3d4e5f6",
ship_data: {
contact_name: "ישראל ישראלי",
contact_phone: "0521234567",
contact_mail: "israel@example.co.il",
street: "הרצל",
number: "10",
city: "תל אביב",
entrance: "ב",
floor: "3",
apartment: "12",
type: "1",
return: "1",
packages: 1,
note: "להשאיר אצל השומר אם אין איש בבית"
},
order: {
id: "1042",
number: "1042",
status: "processing",
currency: "ILS",
total: 249.90,
source: "api",
shipping: {
first_name: "ישראל",
last_name: "ישראלי",
phone: "0521234567",
email: "israel@example.co.il",
address_1: "הרצל",
address_2: "10",
city: "תל אביב",
postcode: "6688312",
country: "IL"
},
order_items: [
{ sku: "TSHIRT-M-BLK", name: "חולצת טי כותנה (M, שחור)", quantity: 2, price: 89.95, total: 179.90 },
{ sku: "SOCKS-3PK", name: "שלישיית גרביים", quantity: 1, price: 70.00, total: 70.00 }
]
}
}
uri = URI("https://app.shipos.co.il/api/v2/shipments")
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["Idempotency-Key"] = "4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f"
request.body = JSON.dump(payload)
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
raise "ShipOS error: #{response.body}" unless response.code == "201"
shipment = JSON.parse(response.body).fetch("data")
puts shipment["uuid"], shipment["tracking_code"]// [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 payload = json!({
"license_key": "a1b2c3d4e5f6",
"ship_data": {
"contact_name": "ישראל ישראלי",
"contact_phone": "0521234567",
"contact_mail": "israel@example.co.il",
"street": "הרצל",
"number": "10",
"city": "תל אביב",
"entrance": "ב",
"floor": "3",
"apartment": "12",
"type": "1",
"return": "1",
"packages": 1,
"note": "להשאיר אצל השומר אם אין איש בבית"
},
"order": {
"id": "1042",
"number": "1042",
"status": "processing",
"currency": "ILS",
"total": 249.90,
"source": "api",
"shipping": {
"first_name": "ישראל",
"last_name": "ישראלי",
"phone": "0521234567",
"email": "israel@example.co.il",
"address_1": "הרצל",
"address_2": "10",
"city": "תל אביב",
"postcode": "6688312",
"country": "IL"
},
"order_items": [
{"sku": "TSHIRT-M-BLK", "name": "חולצת טי כותנה (M, שחור)", "quantity": 2, "price": 89.95, "total": 179.90},
{"sku": "SOCKS-3PK", "name": "שלישיית גרביים", "quantity": 1, "price": 70.00, "total": 70.00}
]
}
});
let created: Value = reqwest::Client::new()
.post("https://app.shipos.co.il/api/v2/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")
.header("Idempotency-Key", "4f9d2c6a-7b1e-4e3a-9c5d-8a0b1c2d3e4f")
.json(&payload)
.send()
.await?
.error_for_status()?
.json()
.await?;
let shipment = &created["data"];
println!("{} {}", shipment["uuid"], shipment["tracking_code"]);
Ok(())
}תגובת 201 Created מחזירה את אובייקט המשלוח המלא:
{
"data": {
"uuid": "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88",
"tracking_code": "66747921",
"carrier": { "id": 4, "name": "HFD" },
"status": null,
"service_type": "1",
"is_active": true,
"recipient": {
"name": "ישראל ישראלי",
"phone": "0521234567",
"company": null,
"address": {
"street": "הרצל",
"number": "10",
"city": "תל אביב",
"state": null,
"zip": "6688312",
"country": "IL"
}
},
"pickup_point_id": null,
"packages": 1,
"cod": null,
"order": { "id": "1042", "number": "1042" },
"references": { "external_id": null },
"short_tracking_code": null,
"label_generated": false,
"collection_status": null,
"collected_at": null,
"ready_at": null,
"created_at": "2026-07-29T09:14:00.000000Z",
"updated_at": "2026-07-29T09:14:00.000000Z"
}
}שמרו את השדות הבאים בצד שלכם:
| שדה | למה |
|---|---|
uuid | מזהה ה-API של המשלוח — נדרש לכל קריאת המשך (/shipments/{shipment}, /status, /label, /cancel). |
tracking_code | קוד המעקב של המוביל. משמש גם עבור ה-endpoint הציבורי למעקב, וזה מה שהלקוח שלכם רואה. |
short_tracking_code | קוד קצר שמשמש בתהליכי נקודות איסוף (עשוי להיות null במשלוחים עד הבית). |
label_generated | האם כבר הופקה תווית — משתלב עם שלב 4. |
שלב 4 — קבלת התווית
GET /shipments/{shipment}/label מחזיר מטא-נתוני תווית עם קישור הורדה — לא את בייטי ה-PDF עצמם:
curl --location 'https://app.shipos.co.il/api/v2/shipments/9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88/label' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'// Node.js 18+ / דפדפנים — ללא תלויות
const uuid = '9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88'
const response = await fetch(
`https://app.shipos.co.il/api/v2/shipments/${uuid}/label`,
{
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: label } = await response.json()
console.log(label.format, label.url) // גשו ל-label.url כדי להוריד את ה-PDF<?php
// composer require guzzlehttp/guzzle
$uuid = '9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88';
$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',
],
]);
$label = json_decode(
$client->get("shipments/{$uuid}/label")->getBody()->getContents(),
true,
)['data'];
echo $label['format'], ' ', $label['url'], PHP_EOL;<?php
use Illuminate\Support\Facades\Http;
$uuid = '9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88';
$label = 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/shipments/{$uuid}/label")
->throw()
->json('data');
// הורדת בייטי ה-PDF — כתובת התווית אינה דורשת פרטי גישה
$pdf = Http::get($label['url'])->throw()->body();# pip install httpx
import os
import httpx
uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88"
response = httpx.get(
f"https://app.shipos.co.il/api/v2/shipments/{shipment}/label",
headers={
"X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
"X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
"Accept": "application/json",
},
)
response.raise_for_status()
label = response.json()["data"]
pdf = httpx.get(label["url"], follow_redirects=True).content
print(label["format"], len(pdf), "bytes")package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type labelResponse struct {
Data struct {
ShipmentID string `json:"shipment_id"`
Format string `json:"format"`
URL string `json:"url"`
} `json:"data"`
}
func main() {
uuid := "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88"
url := fmt.Sprintf("https://app.shipos.co.il/api/v2/shipments/%s/label", uuid)
req, _ := http.NewRequest("GET", url, 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 label labelResponse
if err := json.NewDecoder(res.Body).Decode(&label); err != nil {
panic(err)
}
fmt.Println(label.Data.Format, label.Data.URL)
}// 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 GetLabel {
public static void main(String[] args) throws Exception {
String uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/shipments/" + uuid + "/label"))
.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":{"format":"pdf","url":...}}
}
}// .NET 8+ — System.Net.Http.Json
using System.Net.Http.Json;
using System.Text.Json;
var uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88";
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>($"shipments/{shipment}/label")
?? throw new InvalidOperationException("Empty response");
var label = payload.RootElement.GetProperty("data");
Console.WriteLine($"{label.GetProperty("format").GetString()} " +
$"{label.GetProperty("url").GetString()}");require "net/http"
require "json"
uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88"
uri = URI("https://app.shipos.co.il/api/v2/shipments/#{uuid}/label")
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)
label = JSON.parse(response.body).fetch("data")
puts label["format"], label["url"]// [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 uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88";
let payload: Value = reqwest::Client::new()
.get(format!(
"https://app.shipos.co.il/api/v2/shipments/{shipment}/label"
))
.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 label = &payload["data"];
println!("{} {}", label["format"], label["url"]);
Ok(())
}{
"data": {
"shipment_id": "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88",
"format": "pdf",
"url": "https://app.shipos.co.il/shipping/label/9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88"
}
}גשו אל ה-url כדי להוריד את תווית ה-PDF. שימו לב שהכתובת נמצאת מחוץ ל-/api/v2 ואינה דורשת את כותרות פרטי הלקוח — היכולת היא הידיעה של ה-uuid של המשלוח, לכן התייחסו לקישור עצמו כאל מידע רגיש.
הדפסת תוויות רבות בבת אחת
POST /shipments/labels עם רשימת uuids מחזיר כתובת אחת ל-PDF מאוחד של כולן — ראו את מדריך העזר למשלוחים.
שלב 5 — מעקב
שתי אפשרויות, בהתאם למי ששואל.
מאומת (ה-backend שלכם): GET /shipments/{shipment}/status שולף מחדש את הסטטוס מהמוביל ומחזיר את אובייקט המשלוח המלא והמעודכן (אותו מבנה כמו התגובה בשלב 3, עם status מלא):
curl --location 'https://app.shipos.co.il/api/v2/shipments/9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88/status' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'// Node.js 18+ / דפדפנים — ללא תלויות
const uuid = '9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88'
const response = await fetch(
`https://app.shipos.co.il/api/v2/shipments/${uuid}/status`,
{
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: shipment } = await response.json()
console.log(shipment.status?.description, shipment.status?.is_delivered)<?php
// composer require guzzlehttp/guzzle
$uuid = '9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88';
$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',
],
]);
$shipment = json_decode(
$client->get("shipments/{$uuid}/status")->getBody()->getContents(),
true,
)['data'];
echo $shipment['status']['description'] ?? 'no status yet', PHP_EOL;<?php
use Illuminate\Support\Facades\Http;
$uuid = '9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88';
$shipment = 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/shipments/{$uuid}/status")
->throw()
->json('data');
logger()->info('Shipment status', [
'code' => data_get($shipment, 'status.code'),
'delivered' => data_get($shipment, 'status.is_delivered'),
]);# pip install httpx
import os
import httpx
uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88"
response = httpx.get(
f"https://app.shipos.co.il/api/v2/shipments/{shipment}/status",
headers={
"X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
"X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
"Accept": "application/json",
},
timeout=60.0,
)
response.raise_for_status()
shipment = response.json()["data"]
status = shipment.get("status") or {}
print(status.get("description"), status.get("is_delivered"))package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type statusResponse struct {
Data struct {
TrackingCode string `json:"tracking_code"`
Status *struct {
Code string `json:"code"`
Description string `json:"description"`
IsDelivered bool `json:"is_delivered"`
} `json:"status"`
} `json:"data"`
}
func main() {
uuid := "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88"
url := fmt.Sprintf("https://app.shipos.co.il/api/v2/shipments/%s/status", uuid)
req, _ := http.NewRequest("GET", url, 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 statusResponse
if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
panic(err)
}
if payload.Data.Status != nil {
fmt.Println(payload.Data.Status.Description, payload.Data.Status.IsDelivered)
}
}// 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 RefreshStatus {
public static void main(String[] args) throws Exception {
String uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/shipments/" + uuid + "/status"))
.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":{...,"status":{...}}}
}
}// .NET 8+ — System.Net.Http.Json
using System.Net.Http.Json;
using System.Text.Json;
var uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88";
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>($"shipments/{shipment}/status")
?? throw new InvalidOperationException("Empty response");
var shipment = payload.RootElement.GetProperty("data");
if (shipment.TryGetProperty("status", out var status) &&
status.ValueKind == JsonValueKind.Object)
{
Console.WriteLine($"{status.GetProperty("description").GetString()} " +
$"{status.GetProperty("is_delivered").GetBoolean()}");
}require "net/http"
require "json"
uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88"
uri = URI("https://app.shipos.co.il/api/v2/shipments/#{uuid}/status")
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)
shipment = JSON.parse(response.body).fetch("data")
puts shipment.dig("status", "description"), shipment.dig("status", "is_delivered")// [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 uuid = "9b2c7f1e-3a4d-4c88-9f21-2f0d5a6b7c88";
let payload: Value = reqwest::Client::new()
.get(format!(
"https://app.shipos.co.il/api/v2/shipments/{shipment}/status"
))
.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 status = &payload["data"]["status"];
println!("{} {}", status["description"], status["is_delivered"]);
Ok(())
}סטטוס ללא פרטים אישיים: GET /tracking/{shipping_code} מקבל את ה-tracking_code ומחזיר תצוגת סטטוס ללא פרטי נמען. הוא דורש את פרטי ההזדהות שלכם, ולכן יש לקרוא לו מהשרת — לעולם לא מדפדפן, שם הסוד ייחשף. כדי להציג ללקוחות מעקב, הפיקו אותו מהשרת שלכם או הפנו אותם לקישור שנשלח ב-SMS האיסוף:
curl --location 'https://app.shipos.co.il/api/v2/tracking/66747921' \
--header 'Accept: application/json'// Node.js 18+ / דפדפנים — ללא תלויות, ללא פרטי גישה
const trackingCode = '66747921'
const response = await fetch(
`https://app.shipos.co.il/api/v2/tracking/${trackingCode}`,
{ headers: { Accept: 'application/json' } },
)
if (!response.ok) {
const { error } = await response.json()
throw new Error(`${error.code}: ${error.message}`)
}
const { data: tracking } = await response.json()
console.log(tracking.status.description, tracking.status.is_delivered)<?php
// composer require guzzlehttp/guzzle — endpoint ציבורי, ללא פרטי גישה
$trackingCode = '66747921';
$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.shipos.co.il/api/v2/',
'headers' => ['Accept' => 'application/json'],
]);
$tracking = json_decode(
$client->get("tracking/{$trackingCode}")->getBody()->getContents(),
true,
)['data'];
echo $tracking['status']['description'], PHP_EOL;<?php
use Illuminate\Support\Facades\Http;
$trackingCode = '66747921';
// endpoint ציבורי — ללא פרטי לקוח
$tracking = Http::acceptJson()
->get("https://app.shipos.co.il/api/v2/tracking/{$trackingCode}")
->throw()
->json('data');
logger()->info('Tracking', [
'code' => data_get($tracking, 'status.code'),
'delivered' => data_get($tracking, 'status.is_delivered'),
]);# pip install httpx — endpoint ציבורי, ללא פרטי גישה
import httpx
tracking_code = "66747921"
response = httpx.get(
f"https://app.shipos.co.il/api/v2/tracking/{tracking_code}",
headers={"Accept": "application/json"},
)
response.raise_for_status()
tracking = response.json()["data"]
print(tracking["status"]["description"], tracking["status"]["is_delivered"])package main
import (
"encoding/json"
"fmt"
"net/http"
)
type trackingResponse struct {
Data struct {
TrackingCode string `json:"tracking_code"`
Status struct {
Code string `json:"code"`
Description string `json:"description"`
IsDelivered bool `json:"is_delivered"`
} `json:"status"`
} `json:"data"`
}
func main() {
trackingCode := "66747921"
url := fmt.Sprintf("https://app.shipos.co.il/api/v2/tracking/%s", trackingCode)
// endpoint ציבורי — ללא כותרות פרטי גישה
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var payload trackingResponse
if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
panic(err)
}
fmt.Println(payload.Data.Status.Description, payload.Data.Status.IsDelivered)
}// Java 17+ — java.net.http, endpoint ציבורי, ללא פרטי גישה
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class PublicTracking {
public static void main(String[] args) throws Exception {
String trackingCode = "66747921";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.shipos.co.il/api/v2/tracking/" + trackingCode))
.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":{"tracking_code":...,"status":{...}}}
}
}// .NET 8+ — System.Net.Http.Json, endpoint ציבורי, ללא פרטי גישה
using System.Net.Http.Json;
using System.Text.Json;
var trackingCode = "66747921";
using var http = new HttpClient
{
BaseAddress = new Uri("https://app.shipos.co.il/api/v2/"),
};
var payload = await http.GetFromJsonAsync<JsonDocument>($"tracking/{trackingCode}")
?? throw new InvalidOperationException("Empty response");
var status = payload.RootElement.GetProperty("data").GetProperty("status");
Console.WriteLine($"{status.GetProperty("description").GetString()} " +
$"{status.GetProperty("is_delivered").GetBoolean()}");require "net/http"
require "json"
tracking_code = "66747921"
# endpoint ציבורי — ללא כותרות פרטי גישה
uri = URI("https://app.shipos.co.il/api/v2/tracking/#{tracking_code}")
request = Net::HTTP::Get.new(uri)
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)
tracking = JSON.parse(response.body).fetch("data")
puts tracking.dig("status", "description"), tracking.dig("status", "is_delivered")// [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 tracking_code = "66747921";
// endpoint ציבורי — ללא כותרות פרטי גישה
let payload: Value = reqwest::Client::new()
.get(format!(
"https://app.shipos.co.il/api/v2/tracking/{tracking_code}"
))
.header("Accept", "application/json")
.send()
.await?
.error_for_status()?
.json()
.await?;
let status = &payload["data"]["status"];
println!("{} {}", status["description"], status["is_delivered"]);
Ok(())
}{
"data": {
"tracking_code": "66747921",
"carrier": { "id": 4, "name": "HFD" },
"status": {
"code": "3",
"description": "יצא לחלוקה",
"is_delivered": false
},
"is_active": true,
"updated_at": "2026-07-30T07:41:12.000000Z"
}
}לפרטים ראו את מדריך העזר למעקב.
מה יכול להשתבש
כל השגיאות משתמשות במעטפת { "error": { "code", "message", "status", "details" } }. אלו שתפגשו בתהליך הזה:
| HTTP | error.code | משמעות | מה לעשות |
|---|---|---|---|
422 | validation_failed | הגוף נכשל בוולידציה — שדה חובה של ship_data/order חסר או פגום, או ש-license_key הושמט כשלחשבון יש כמה רישיונות פעילים. | תקנו את השדות המפורטים ב-error.details ושלחו מחדש. |
403 | package_limit_reached | מכסת המשלוחים של המנוי שלכם נוצלה במלואה. המוביל לא נקרא. | שדרגו את החבילה / פנו לתמיכה; ניסיון חוזר לא יעזור. |
424 | carrier_error | המוביל דחה את המשלוח (כתובת שגויה, תקלה בצד המוביל, ...). דבר לא נשמר. | בדקו את error.message, תקנו את הנתונים ונסו שוב — עם Idempotency-Key חדש אם הגוף השתנה. |
409 | idempotency_key_conflict | אותו Idempotency-Key שימש שוב עם גוף בקשה שונה. | השתמשו במפתח אחד לכל משלוח לוגי; צרו מפתח חדש למשלוח חדש באמת. |
409 | duplicate_request | משלוח עבור בדיוק אותה בקשה כבר נמצא בתהליך יצירה במקביל. | המתינו רגע ונסו שוב עם אותו מפתח — תקבלו בחזרה את המשלוח שהושלם. |
הקטלוג המלא במדריך השגיאות; סמנטיקת האידמפוטנטיות באידמפוטנטיות.