Skip to content

Pickup points

Lists the carrier pickup points available to the selected license. The points returned belong to the caller license's carrier: a HFD license returns HFD points, a Cargo license returns Cargo points, and so on. A carrier with no pickup network returns an empty list.

This endpoint is license-scoped: it operates under a single License chosen with the license_key query parameter, whose value is the License's key. With one active license it is used by default; with several, license_key is required (otherwise 422); a key that is missing, inactive, expired, or not owned returns 403.


GET /pickup-points

Return the selected license's carrier pickup points, optionally filtered by city and/or ranked nearest-first around an origin. Auth: client credentials. License: required.

Parameters

Query

FieldTypeRequiredDescription
license_keystringconditionalThe License key to act under. Required when the account owns more than one active license.
citystringnoCase-insensitive substring filter on the point's city (max 255 chars).
limitintegernoCap the number of points returned (min 1, capped at 500). Applied after ranking, so with an origin it yields the N closest.
latnumbernoOrigin latitude (-90..90) for nearest-first ranking. Must be sent together with lng.
lngnumbernoOrigin longitude (-180..180) for nearest-first ranking. Must be sent together with lat.
addressstringnoFree-text origin address (max 500 chars). Geocoded to coordinates for nearest-first ranking. Ignored when explicit lat/lng are supplied.

How ranking works

By default the list is returned unranked (carrier order) and no distance_km is included.

To rank nearest-first you supply an origin, in one of two ways:

  1. Explicit coordinates — send both lat and lng. No geocoding, no API key needed. Sending only one of the pair is a validation error.
  2. Address — send address (and optionally city, which is passed through to the geocoder). The address is geocoded using the merchant's own key: Google Geocoding when a google_api_key is configured, otherwise Geoapify when a geoapify_api_key is configured. If neither key is set, no geocoding call is made and the list is returned unranked. (Accounts created before 2025-08-10 fall back to a shared Google key.) Any geocoding failure — no key, provider error, or no match — degrades gracefully to an unranked list rather than erroring.

When an origin is resolved, each point gets a distance_km (great-circle distance from the origin, in kilometres, rounded to 3 decimals) and the list is sorted closest-first. Points that have no coordinates keep distance_km: null and sort last.

distance_km appears only when an origin was supplied (explicit lat/lng, or a successfully geocoded address). On a plain or city-only listing the key is absent.

Example request — plain list

bash
curl --location 'https://app.shipos.co.il/api/v2/pickup-points' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'
js
// Node.js 18+ / browsers — no dependencies
const response = await fetch('https://app.shipos.co.il/api/v2/pickup-points', {
  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: points } = await response.json()

for (const point of points) {
  console.log(point.id, point.name, point.address.city)
}
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',
    ],
]);

$points = json_decode(
    $client->get('pickup-points')->getBody()->getContents(),
    true,
)['data'];

foreach ($points as $point) {
    echo $point['id'], ' ', $point['name'], ' ', $point['address']['city'], PHP_EOL;
}
php
<?php

use Illuminate\Support\Facades\Http;

$points = 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/pickup-points')
    ->throw()
    ->json('data');

foreach ($points as $point) {
    logger()->info($point['id'].' '.$point['name'].' '.$point['address']['city']);
}
python
# pip install httpx
import os

import httpx

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

for point in points:
    print(point["id"], point["name"], point["address"]["city"])
go
package main

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

type pickupPointsResponse struct {
	Data []struct {
		ID      string `json:"id"`
		Name    string `json:"name"`
		Address struct {
			City string `json:"city"`
		} `json:"address"`
	} `json:"data"`
}

func main() {
	req, _ := http.NewRequest("GET",
		"https://app.shipos.co.il/api/v2/pickup-points", 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 pickupPointsResponse
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	for _, point := range payload.Data {
		fmt.Println(point.ID, point.Name, point.Address.City)
	}
}
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 ShipOsPickupPoints {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/pickup-points"))
            .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>("pickup-points")
    ?? throw new InvalidOperationException("Empty response");

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

uri = URI("https://app.shipos.co.il/api/v2/pickup-points")
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 |point|
  puts "#{point["id"]} #{point["name"]} #{point.dig("address", "city")}"
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/pickup-points")
        .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(points) = payload["data"].as_array() {
        for point in points {
            println!("{} {}", point["id"], point["name"]);
        }
    }
    Ok(())
}

Example request — city filter

bash
curl --location 'https://app.shipos.co.il/api/v2/pickup-points?city=Tel%20Aviv&limit=50' \
--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({ city: 'Tel Aviv', limit: '50' })

const response = await fetch(
  `https://app.shipos.co.il/api/v2/pickup-points?${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: points } = await response.json()

for (const point of points) {
  console.log(point.id, point.name, point.address.street, point.address.house)
}
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('pickup-points', [
    'query' => ['city' => 'Tel Aviv', 'limit' => 50],
]);
$points = json_decode($response->getBody()->getContents(), true)['data'];

foreach ($points as $point) {
    echo $point['id'], ' ', $point['name'], PHP_EOL;
}
php
<?php

use Illuminate\Support\Facades\Http;

$points = 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/pickup-points', [
        'city' => 'Tel Aviv',
        'limit' => 50,
    ])
    ->throw()
    ->json('data');

foreach ($points as $point) {
    logger()->info($point['id'].' '.$point['name']);
}
python
# pip install httpx
import os

import httpx

response = httpx.get(
    "https://app.shipos.co.il/api/v2/pickup-points",
    params={"city": "Tel Aviv", "limit": 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()
points = response.json()["data"]

for point in points:
    print(point["id"], point["name"], point["address"]["street"])
go
package main

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

type pickupPointsResponse struct {
	Data []struct {
		ID   string `json:"id"`
		Name string `json:"name"`
	} `json:"data"`
}

func main() {
	query := url.Values{"city": {"Tel Aviv"}, "limit": {"50"}}
	req, _ := http.NewRequest("GET",
		"https://app.shipos.co.il/api/v2/pickup-points?"+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 pickupPointsResponse
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	for _, point := range payload.Data {
		fmt.Println(point.ID, point.Name)
	}
}
java
// Java 17+ — java.net.http, no dependencies (parse with Jackson/Gson)
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;

public class ShipOsPickupPointsByCity {
    public static void main(String[] args) throws Exception {
        String query = "city=" + URLEncoder.encode("Tel Aviv", StandardCharsets.UTF_8)
            + "&limit=50";

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/pickup-points?" + 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":[...]}
    }
}
csharp
// .NET 8+ — System.Net.Http.Json
using System.Net.Http.Json;
using System.Text.Json;
using System.Web;

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 query = HttpUtility.ParseQueryString(string.Empty);
query["city"] = "Tel Aviv";
query["limit"] = "50";

var payload = await http.GetFromJsonAsync<JsonDocument>($"pickup-points?{query}")
    ?? throw new InvalidOperationException("Empty response");

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

uri = URI("https://app.shipos.co.il/api/v2/pickup-points")
uri.query = URI.encode_www_form(city: "Tel Aviv", limit: 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 |point|
  puts "#{point["id"]} #{point["name"]}"
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/pickup-points")
        .query(&[("city", "Tel Aviv"), ("limit", "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?;

    if let Some(points) = payload["data"].as_array() {
        for point in points {
            println!("{} {}", point["id"], point["name"]);
        }
    }
    Ok(())
}

Example request — nearest by coordinates

bash
curl --location 'https://app.shipos.co.il/api/v2/pickup-points?lat=32.0853&lng=34.7818&limit=10' \
--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({
  lat: '32.0853',
  lng: '34.7818',
  limit: '10',
})

const response = await fetch(
  `https://app.shipos.co.il/api/v2/pickup-points?${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: points } = await response.json()

for (const point of points) {
  console.log(point.name, `${point.distance_km ?? '?'} km`)
}
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('pickup-points', [
    'query' => ['lat' => 32.0853, 'lng' => 34.7818, 'limit' => 10],
]);
$points = json_decode($response->getBody()->getContents(), true)['data'];

foreach ($points as $point) {
    echo $point['name'], ' ', $point['distance_km'] ?? '?', ' km', PHP_EOL;
}
php
<?php

use Illuminate\Support\Facades\Http;

$points = 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/pickup-points', [
        'lat' => 32.0853,
        'lng' => 34.7818,
        'limit' => 10,
    ])
    ->throw()
    ->json('data');

foreach ($points as $point) {
    logger()->info($point['name'].' '.($point['distance_km'] ?? '?').' km');
}
python
# pip install httpx
import os

import httpx

response = httpx.get(
    "https://app.shipos.co.il/api/v2/pickup-points",
    params={"lat": 32.0853, "lng": 34.7818, "limit": 10},
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
)
response.raise_for_status()
points = response.json()["data"]

for point in points:
    print(point["name"], point.get("distance_km"), "km")
go
package main

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

type nearestPointsResponse struct {
	Data []struct {
		Name       string   `json:"name"`
		DistanceKm *float64 `json:"distance_km"`
	} `json:"data"`
}

func main() {
	query := url.Values{
		"lat":   {"32.0853"},
		"lng":   {"34.7818"},
		"limit": {"10"},
	}
	req, _ := http.NewRequest("GET",
		"https://app.shipos.co.il/api/v2/pickup-points?"+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 nearestPointsResponse
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	for _, point := range payload.Data {
		fmt.Println(point.Name, point.DistanceKm)
	}
}
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 ShipOsNearestPickupPoints {
    public static void main(String[] args) throws Exception {
        String query = "lat=32.0853&lng=34.7818&limit=10";

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/pickup-points?" + 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()); // nearest-first, with distance_km
    }
}
csharp
// .NET 8+ — System.Net.Http.Json
using System.Net.Http.Json;
using System.Text.Json;
using System.Web;

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 query = HttpUtility.ParseQueryString(string.Empty);
query["lat"] = "32.0853";
query["lng"] = "34.7818";
query["limit"] = "10";

var payload = await http.GetFromJsonAsync<JsonDocument>($"pickup-points?{query}")
    ?? throw new InvalidOperationException("Empty response");

foreach (var point in payload.RootElement.GetProperty("data").EnumerateArray())
{
    Console.WriteLine($"{point.GetProperty("name").GetString()} " +
        $"{point.GetProperty("distance_km")} km");
}
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/pickup-points")
uri.query = URI.encode_www_form(lat: 32.0853, lng: 34.7818, limit: 10)

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 |point|
  puts "#{point["name"]} #{point["distance_km"]} km"
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/pickup-points")
        .query(&[("lat", "32.0853"), ("lng", "34.7818"), ("limit", "10")])
        .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(points) = payload["data"].as_array() {
        for point in points {
            println!("{} {} km", point["name"], point["distance_km"]);
        }
    }
    Ok(())
}

Example request — nearest by address

bash
curl --location 'https://app.shipos.co.il/api/v2/pickup-points?address=Herzl%2010%2C%20Tel%20Aviv&limit=10' \
--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({
  address: 'Herzl 10, Tel Aviv',
  limit: '10',
})

const response = await fetch(
  `https://app.shipos.co.il/api/v2/pickup-points?${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: points } = await response.json()

// distance_km is absent when geocoding could not resolve the address
for (const point of points) {
  console.log(point.name, point.distance_km ?? 'unranked')
}
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('pickup-points', [
    'query' => ['address' => 'Herzl 10, Tel Aviv', 'limit' => 10],
]);
$points = json_decode($response->getBody()->getContents(), true)['data'];

foreach ($points as $point) {
    echo $point['name'], ' ', $point['distance_km'] ?? 'unranked', PHP_EOL;
}
php
<?php

use Illuminate\Support\Facades\Http;

$points = 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/pickup-points', [
        'address' => 'Herzl 10, Tel Aviv',
        'limit' => 10,
    ])
    ->throw()
    ->json('data');

foreach ($points as $point) {
    logger()->info($point['name'].' '.($point['distance_km'] ?? 'unranked'));
}
python
# pip install httpx
import os

import httpx

response = httpx.get(
    "https://app.shipos.co.il/api/v2/pickup-points",
    params={"address": "Herzl 10, Tel Aviv", "limit": 10},
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
)
response.raise_for_status()
points = response.json()["data"]

# distance_km is absent when geocoding could not resolve the address
for point in points:
    print(point["name"], point.get("distance_km", "unranked"))
go
package main

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

type addressPointsResponse struct {
	Data []struct {
		Name       string   `json:"name"`
		DistanceKm *float64 `json:"distance_km"`
	} `json:"data"`
}

func main() {
	query := url.Values{
		"address": {"Herzl 10, Tel Aviv"},
		"limit":   {"10"},
	}
	req, _ := http.NewRequest("GET",
		"https://app.shipos.co.il/api/v2/pickup-points?"+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 addressPointsResponse
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	for _, point := range payload.Data {
		fmt.Println(point.Name, point.DistanceKm)
	}
}
java
// Java 17+ — java.net.http, no dependencies (parse with Jackson/Gson)
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;

public class ShipOsPickupPointsByAddress {
    public static void main(String[] args) throws Exception {
        String query = "address="
            + URLEncoder.encode("Herzl 10, Tel Aviv", StandardCharsets.UTF_8)
            + "&limit=10";

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/pickup-points?" + 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()); // unranked when geocoding failed
    }
}
csharp
// .NET 8+ — System.Net.Http.Json
using System.Net.Http.Json;
using System.Text.Json;
using System.Web;

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 query = HttpUtility.ParseQueryString(string.Empty);
query["address"] = "Herzl 10, Tel Aviv";
query["limit"] = "10";

var payload = await http.GetFromJsonAsync<JsonDocument>($"pickup-points?{query}")
    ?? throw new InvalidOperationException("Empty response");

foreach (var point in payload.RootElement.GetProperty("data").EnumerateArray())
{
    point.TryGetProperty("distance_km", out var distance);
    Console.WriteLine($"{point.GetProperty("name").GetString()} {distance}");
}
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/pickup-points")
uri.query = URI.encode_www_form(address: "Herzl 10, Tel Aviv", limit: 10)

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 |point|
  puts "#{point["name"]} #{point.fetch("distance_km", "unranked")}"
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/pickup-points")
        .query(&[("address", "Herzl 10, Tel Aviv"), ("limit", "10")])
        .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(points) = payload["data"].as_array() {
        for point in points {
            println!("{} {}", point["name"], point["distance_km"]);
        }
    }
    Ok(())
}

Response 200

Without an origin (plain / city-filtered list) — no distance_km:

json
{
  "data": [
    {
      "id": "12345",
      "name": "SuperPharm Dizengoff",
      "type": "locker",
      "address": {
        "city": "Tel Aviv",
        "street": "Dizengoff",
        "house": "50"
      },
      "coordinates": {
        "latitude": 32.0791,
        "longitude": 34.7742
      }
    }
  ]
}

With an origin (lat/lng or geocoded address) — distance_km present, nearest first:

json
{
  "data": [
    {
      "id": "12345",
      "name": "SuperPharm Dizengoff",
      "type": "locker",
      "address": {
        "city": "Tel Aviv",
        "street": "Dizengoff",
        "house": "50"
      },
      "coordinates": {
        "latitude": 32.0791,
        "longitude": 34.7742
      },
      "distance_km": 0.842
    },
    {
      "id": "67890",
      "name": "Point with no geocode",
      "type": "store",
      "address": {
        "city": "Tel Aviv",
        "street": "Allenby",
        "house": "3"
      },
      "coordinates": {
        "latitude": null,
        "longitude": null
      },
      "distance_km": null
    }
  ]
}

Pickup point fields

FieldTypeDescription
idstringCarrier-agnostic point id.
namestring | nullPoint display name.
typestring | nullPoint type as reported by the carrier (e.g. locker, store), when available.
address.citystring | nullCity.
address.streetstring | nullStreet.
address.housestring | nullHouse / street number.
coordinates.latitudenumber | nullLatitude, or null when the carrier did not provide one.
coordinates.longitudenumber | nullLongitude, or null when the carrier did not provide one.
distance_kmnumber | nullKilometres from the supplied origin. Present only when an origin was supplied; null for points without coordinates.

Errors

StatuscodeWhen
401unauthenticatedMissing or invalid client credentials.
403forbiddenAccount has no active license, or the given license_key is inactive / expired / not owned by you.
422validation_failedInvalid query params (e.g. only one of lat/lng, out-of-range coordinates, limit < 1), or multiple active licenses and license_key omitted.