Skip to content

התראות (SMS)

הגדרה ותפעול של התראות SMS ללקוחות: פרטי ההתחברות לספק ה-SMS, תבניות הודעה לפי שיטת משלוח, שליחת בדיקה חד-פעמית ויומן שליחות עם חיפוש.

מידע

ה-endpoints האלה הם ברמת חשבון לקוח (customer-scoped), לא ברמת רישיון — הם פועלים על חשבון הסוחר המאומת שמאחורי ה-client credentials שלכם ומכסים את כל המשלוחים שלו. הם אינם קוראים license_key.


GET /notifications/sms-settings

מחזיר את הגדרות ספק ה-SMS של חשבון הקורא (singleton — תמיד 200). אימות: client credentials.

פרמטרים

אין.

בקשה לדוגמה

bash
curl --location 'https://app.shipos.co.il/api/v2/notifications/sms-settings' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch(
  'https://app.shipos.co.il/api/v2/notifications/sms-settings',
  {
    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: settings } = await response.json()

console.log(settings.sender_name, settings.configured)
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',
    ],
]);

$settings = json_decode(
    $client->get('notifications/sms-settings')->getBody()->getContents(),
    true,
)['data'];

echo $settings['sender_name'], ' configured: ',
    var_export($settings['configured'], true), PHP_EOL;
php
<?php

use Illuminate\Support\Facades\Http;

$settings = 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/notifications/sms-settings')
    ->throw()
    ->json('data');

logger()->info($settings['sender_name'], ['configured' => $settings['configured']]);
python
# pip install httpx
import os

import httpx

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

print(settings["sender_name"], settings["configured"])
go
package main

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

type smsSettingsResponse struct {
	Data struct {
		SenderName string `json:"sender_name"`
		Configured bool   `json:"configured"`
	} `json:"data"`
}

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

	fmt.Println(payload.Data.SenderName, payload.Data.Configured)
}
java
// 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 ShipOsSmsSettings {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/notifications/sms-settings"))
            .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 =
            client.send(request, HttpResponse.BodyHandlers.ofString());

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

        System.out.println(response.body()); // {"data":{...}} — למפו עם Jackson/Gson
    }
}
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>("notifications/sms-settings")
    ?? throw new InvalidOperationException("Empty response");
var settings = payload.RootElement.GetProperty("data");

Console.WriteLine(settings.GetProperty("sender_name").GetString());
Console.WriteLine(settings.GetProperty("configured").GetBoolean());
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/notifications/sms-settings")
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)

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

puts "#{settings["sender_name"]} configured: #{settings["configured"]}"
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/notifications/sms-settings")
        .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 settings = &payload["data"];
    println!("{} {}", settings["sender_name"], settings["configured"]);
    Ok(())
}

תגובה 200

json
{
  "data": {
    "id": 42,
    "username": "shipos_dafni",
    "sender_name": "DafniHair",
    "has_token": true,
    "configured": true,
    "created_at": "2026-01-01T00:00:00.000000Z",
    "updated_at": "2026-07-20T12:30:00.000000Z"
  }
}

שדות

שדהסוגתיאור
idintמזהה רשומת הגדרות ה-SMS.
usernamestring | nullשם המשתמש בחשבון הספק.
sender_namestring | nullשם השולח של ה-SMS המוצג לנמענים.
has_tokenboolהאם מאוחסן token של API (ה-token עצמו לעולם אינו מוחזר).
configuredbooltrue כאשר גם username וגם token קיימים, כלומר השליחה מוגדרת.
created_atstringחותמת זמן יצירה.
updated_atstringחותמת זמן עדכון.

אזהרה

ה-token של הספק (וכל password) הוא write-only ולעולם אינו מוחזר. התגובה מאותתת על קיומו רק דרך has_token / configured.

שגיאות

סטטוסקודמתי
401unauthenticatedclient credentials חסרים או שגויים.

PUT /notifications/sms-settings

שומר את הגדרות ספק ה-SMS של חשבון הקורא ומחזיר את ה-singleton המעודכן (תמיד 200). אימות: client credentials.

פרמטרים

Body

שדהסוגחובהתיאור
usernamestringכןשם המשתמש בחשבון הספק. עד 255 תווים.
tokenstringכןtoken של ה-API של הספק (write-only; נשמר, לעולם אינו מוחזר).
sender_namestringכןשם השולח של ה-SMS. עד 255 תווים.

בקשה לדוגמה

bash
curl --location --request PUT 'https://app.shipos.co.il/api/v2/notifications/sms-settings' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
  "username": "shipos_dafni",
  "token": "provider-api-token-value",
  "sender_name": "DafniHair"
}'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch(
  'https://app.shipos.co.il/api/v2/notifications/sms-settings',
  {
    method: 'PUT',
    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({
      username: 'shipos_dafni',
      token: 'provider-api-token-value',
      sender_name: 'DafniHair',
    }),
  },
)

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

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

console.log(settings.sender_name, settings.configured)
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->put('notifications/sms-settings', [
    'json' => [
        'username' => 'shipos_dafni',
        'token' => 'provider-api-token-value',
        'sender_name' => 'DafniHair',
    ],
]);

$settings = json_decode($response->getBody()->getContents(), true)['data'];

echo $settings['sender_name'], ' configured: ',
    var_export($settings['configured'], true), PHP_EOL;
php
<?php

use Illuminate\Support\Facades\Http;

$settings = Http::withHeaders([
    'X-Client-Id' => config('services.shipos.client_id'),
    'X-Client-Secret' => config('services.shipos.client_secret'),
])
    ->acceptJson()
    ->put('https://app.shipos.co.il/api/v2/notifications/sms-settings', [
        'username' => 'shipos_dafni',
        'token' => 'provider-api-token-value',
        'sender_name' => 'DafniHair',
    ])
    ->throw()
    ->json('data');

logger()->info($settings['sender_name'], ['configured' => $settings['configured']]);
python
# pip install httpx
import os

import httpx

response = httpx.put(
    "https://app.shipos.co.il/api/v2/notifications/sms-settings",
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
    json={
        "username": "shipos_dafni",
        "token": "provider-api-token-value",
        "sender_name": "DafniHair",
    },
)
response.raise_for_status()
settings = response.json()["data"]

print(settings["sender_name"], settings["configured"])
go
package main

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

func main() {
	body, _ := json.Marshal(map[string]string{
		"username":    "shipos_dafni",
		"token":       "provider-api-token-value",
		"sender_name": "DafniHair",
	})

	req, _ := http.NewRequest("PUT",
		"https://app.shipos.co.il/api/v2/notifications/sms-settings",
		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()

	var payload struct {
		Data struct {
			SenderName string `json:"sender_name"`
			Configured bool   `json:"configured"`
		} `json:"data"`
	}
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	fmt.Println(payload.Data.SenderName, payload.Data.Configured)
}
java
// 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 ShipOsUpdateSmsSettings {
    public static void main(String[] args) throws Exception {
        String body = """
            {"username":"shipos_dafni","token":"provider-api-token-value","sender_name":"DafniHair"}
            """;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/notifications/sms-settings"))
            .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")
            .PUT(HttpRequest.BodyPublishers.ofString(body))
            .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
    }
}
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 response = await http.PutAsJsonAsync("notifications/sms-settings", new
{
    username = "shipos_dafni",
    token = "provider-api-token-value",
    sender_name = "DafniHair",
});
response.EnsureSuccessStatusCode();

var payload = await response.Content.ReadFromJsonAsync<JsonDocument>()
    ?? throw new InvalidOperationException("Empty response");
var settings = payload.RootElement.GetProperty("data");

Console.WriteLine(settings.GetProperty("sender_name").GetString());
Console.WriteLine(settings.GetProperty("configured").GetBoolean());
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/notifications/sms-settings")
request = Net::HTTP::Put.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({
  username: "shipos_dafni",
  token: "provider-api-token-value",
  sender_name: "DafniHair",
})

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)

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

puts "#{settings["sender_name"]} configured: #{settings["configured"]}"
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()
        .put("https://app.shipos.co.il/api/v2/notifications/sms-settings")
        .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(&serde_json::json!({
            "username": "shipos_dafni",
            "token": "provider-api-token-value",
            "sender_name": "DafniHair",
        }))
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;

    let settings = &payload["data"];
    println!("{} {}", settings["sender_name"], settings["configured"]);
    Ok(())
}

תגובה 200

json
{
  "data": {
    "id": 42,
    "username": "shipos_dafni",
    "sender_name": "DafniHair",
    "has_token": true,
    "configured": true,
    "created_at": "2026-01-01T00:00:00.000000Z",
    "updated_at": "2026-07-29T10:00:00.000000Z"
  }
}

שגיאות

סטטוסקודמתי
401unauthenticatedclient credentials חסרים או שגויים.
422validation_failedusername, token או sender_name חסרים או ארוכים מדי.

POST /notifications/test-sms

שולח SMS בדיקה חד-פעמי דרך הספק המוגדר של החשבון. אימות: client credentials.

פרמטרים

Body

שדהסוגחובהתיאור
phonestringכןמספר טלפון היעד. עד 20 תווים.
messagestringכןגוף ההודעה (HTML מותר; מעובד לטקסט רגיל לפני השליחה). עד 1000 תווים.

בקשה לדוגמה

bash
curl --location --request POST 'https://app.shipos.co.il/api/v2/notifications/test-sms' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
  "phone": "0501234567",
  "message": "הודעת בדיקה מ-ShipOS"
}'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch(
  'https://app.shipos.co.il/api/v2/notifications/test-sms',
  {
    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({
      phone: '0501234567',
      message: 'הודעת בדיקה מ-ShipOS',
    }),
  },
)

// 424 עדיין מחזיר payload של `data` — הספק פשוט סירב.
const { data: result } = await response.json()

console.log(result.sent, result.provider_status, result.message)
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',
    ],
]);

// http_errors => false כדי שה-payload של 424 ("הספק דחה") יהיה קריא.
$response = $client->post('notifications/test-sms', [
    'json' => [
        'phone' => '0501234567',
        'message' => 'הודעת בדיקה מ-ShipOS',
    ],
    'http_errors' => false,
]);

$result = json_decode($response->getBody()->getContents(), true)['data'];

echo var_export($result['sent'], true), ' ', $result['message'], PHP_EOL;
php
<?php

use Illuminate\Support\Facades\Http;

$result = 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/notifications/test-sms', [
        'phone' => '0501234567',
        'message' => 'הודעת בדיקה מ-ShipOS',
    ])
    ->throwIfStatus(fn (int $status) => $status !== 424)
    ->json('data');

logger()->info($result['message'], ['sent' => $result['sent']]);
python
# pip install httpx
import os

import httpx

response = httpx.post(
    "https://app.shipos.co.il/api/v2/notifications/test-sms",
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
    json={"phone": "0501234567", "message": "הודעת בדיקה מ-ShipOS"},
)
if response.status_code != 424:  # 424 = הספק דחה, עדיין payload של data
    response.raise_for_status()
result = response.json()["data"]

print(result["sent"], result["provider_status"], result["message"])
go
package main

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

func main() {
	body, _ := json.Marshal(map[string]string{
		"phone":   "0501234567",
		"message": "הודעת בדיקה מ-ShipOS",
	})

	req, _ := http.NewRequest("POST",
		"https://app.shipos.co.il/api/v2/notifications/test-sms",
		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()

	// גם 200 וגם 424 נושאים payload של data.
	var payload struct {
		Data struct {
			Sent           bool   `json:"sent"`
			ProviderStatus string `json:"provider_status"`
			Message        string `json:"message"`
		} `json:"data"`
	}
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	fmt.Println(payload.Data.Sent, payload.Data.ProviderStatus, payload.Data.Message)
}
java
// 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 ShipOsTestSms {
    public static void main(String[] args) throws Exception {
        String body = """
            {"phone":"0501234567","message":"הודעת בדיקה מ-ShipOS"}
            """;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/notifications/test-sms"))
            .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());

        // 200 = התקבל, 424 = הספק דחה (שניהם payloads של data).
        if (response.statusCode() != 200 && response.statusCode() != 424) {
            throw new RuntimeException("ShipOS error: " + response.body());
        }

        System.out.println(response.body()); // {"data":{...}} — למפו עם Jackson/Gson
    }
}
csharp
// .NET 8+ — System.Net.Http.Json
using System.Net;
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 response = await http.PostAsJsonAsync("notifications/test-sms", new
{
    phone = "0501234567",
    message = "הודעת בדיקה מ-ShipOS",
});

// 424 FailedDependency = הספק דחה, עדיין payload של data.
if (!response.IsSuccessStatusCode && response.StatusCode != HttpStatusCode.FailedDependency)
{
    response.EnsureSuccessStatusCode();
}

var payload = await response.Content.ReadFromJsonAsync<JsonDocument>()
    ?? throw new InvalidOperationException("Empty response");
var result = payload.RootElement.GetProperty("data");

Console.WriteLine($"{result.GetProperty("sent").GetBoolean()} " +
    $"{result.GetProperty("message").GetString()}");
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/notifications/test-sms")
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({ phone: "0501234567", message: "הודעת בדיקה מ-ShipOS" })

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

# 424 = הספק דחה, עדיין payload של data.
unless response.is_a?(Net::HTTPSuccess) || response.code == "424"
  raise "ShipOS error: #{response.body}"
end

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

puts "#{result["sent"]} #{result["provider_status"]} #{result["message"]}"
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>> {
    // גם 424 מחזיר payload של data — הספק סירב לשליחה.
    let payload: Value = reqwest::Client::new()
        .post("https://app.shipos.co.il/api/v2/notifications/test-sms")
        .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(&serde_json::json!({
            "phone": "0501234567",
            "message": "הודעת בדיקה מ-ShipOS",
        }))
        .send()
        .await?
        .json()
        .await?;

    let result = &payload["data"];
    println!("{} {}", result["sent"], result["message"]);
    Ok(())
}

תגובה 200

json
{
  "data": {
    "sent": true,
    "provider_status": "OK",
    "message": "Message accepted"
  }
}
שדהסוגתיאור
sentboolהאם הספק קיבל את השליחה.
provider_statusstringסטטוס גולמי של הספק.
messagestringהודעה שמחזיר הספק המתארת את התוצאה.

תגובה 424 (הספק דחה)

כאשר הספק דוחה את השליחה, ה-endpoint מחזיר HTTP 424 Failed Dependency — אבל עדיין כ-payload רגיל של data (לא מעטפת error), כך שתוכלו להבחין בין "ניסינו, הספק סירב" לבין 4xx ברמת הבקשה:

json
{
  "data": {
    "sent": false,
    "provider_status": "REJECTED",
    "message": "Insufficient balance"
  }
}

שגיאות

סטטוסקודמתי
401unauthenticatedclient credentials חסרים או שגויים.
422validation_failedphone או message חסרים או ארוכים מדי.
424הספק דחה את השליחה. מוחזר כ-payload של data עם sent: false (ראו לעיל), לא כמעטפת error.

GET /notifications/sms-logs

מציג את יומני ה-SMS של חשבון הקורא, עם סינון אופציונלי. עם עימוד. אימות: client credentials.

פרמטרים

Query

שדהסוגחובהתיאור
filter[shipping_id]intלאהגבלה ליומנים של משלוח בודד.
filter[success]booleanלאהגבלה לשליחות מוצלחות (true) או כושלות (false).
per_pageintלאפריטים לעמוד. ברירת מחדל 25, מקסימום 100.

בקשה לדוגמה

bash
curl --location 'https://app.shipos.co.il/api/v2/notifications/sms-logs?filter[success]=false&per_page=50' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const query = new URLSearchParams({
  'filter[success]': 'false',
  per_page: '50',
})

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

console.log(meta.total)
for (const log of logs) {
  console.log(log.phone, log.success, log.provider.message)
}
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('notifications/sms-logs', [
    'query' => [
        'filter' => ['success' => 'false'],
        'per_page' => 50,
    ],
]);

$payload = json_decode($response->getBody()->getContents(), true);

echo $payload['meta']['total'], PHP_EOL;
foreach ($payload['data'] as $log) {
    echo $log['phone'], ' ', var_export($log['success'], true), PHP_EOL;
}
php
<?php

use Illuminate\Support\Facades\Http;

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

logger()->info('SMS logs', ['total' => $payload['meta']['total']]);
foreach ($payload['data'] as $log) {
    logger()->info($log['phone'], ['success' => $log['success']]);
}
python
# pip install httpx
import os

import httpx

response = httpx.get(
    "https://app.shipos.co.il/api/v2/notifications/sms-logs",
    params={"filter[success]": "false", "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()
payload = response.json()

print(payload["meta"]["total"])
for log in payload["data"]:
    print(log["phone"], log["success"], log["provider"]["message"])
go
package main

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

type smsLogsResponse struct {
	Data []struct {
		Phone   string `json:"phone"`
		Success bool   `json:"success"`
	} `json:"data"`
	Meta struct {
		Total int `json:"total"`
	} `json:"meta"`
}

func main() {
	query := url.Values{}
	query.Set("filter[success]", "false")
	query.Set("per_page", "50")

	req, _ := http.NewRequest("GET",
		"https://app.shipos.co.il/api/v2/notifications/sms-logs?"+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 smsLogsResponse
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	fmt.Println(payload.Meta.Total)
	for _, log := range payload.Data {
		fmt.Println(log.Phone, log.Success)
	}
}
java
// Java 17+ — java.net.http, ללא תלויות (פענוח עם 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 ShipOsSmsLogs {
    public static void main(String[] args) throws Exception {
        String query = URLEncoder.encode("filter[success]", StandardCharsets.UTF_8)
            + "=false&per_page=50";

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/notifications/sms-logs?" + 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":[...]} — למפו עם Jackson/Gson
    }
}
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["filter[success]"] = "false";
query["per_page"] = "50";

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

Console.WriteLine(payload.RootElement.GetProperty("meta").GetProperty("total").GetInt32());
foreach (var log in payload.RootElement.GetProperty("data").EnumerateArray())
{
    Console.WriteLine($"{log.GetProperty("phone").GetString()} " +
        $"{log.GetProperty("success").GetBoolean()}");
}
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/notifications/sms-logs")
uri.query = URI.encode_www_form("filter[success]" => "false", "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)

payload = JSON.parse(response.body)

puts payload.dig("meta", "total")
payload["data"].each do |log|
  puts "#{log["phone"]} #{log["success"]}"
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/notifications/sms-logs")
        .query(&[("filter[success]", "false"), ("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?;

    println!("{}", payload["meta"]["total"]);
    if let Some(logs) = payload["data"].as_array() {
        for log in logs {
            println!("{} {}", log["phone"], log["success"]);
        }
    }
    Ok(())
}

תגובה 200

json
{
  "data": [
    {
      "id": 90321,
      "shipment_id": "b7e2c1a0-...",
      "shipping_method": "hfd",
      "phone": "0501234567",
      "message": "ההזמנה שלך בדרך!",
      "success": true,
      "state": "sent",
      "provider": { "status": "OK", "message": "Delivered" },
      "created_at": "2026-07-29T09:00:00.000000Z",
      "updated_at": "2026-07-29T09:00:02.000000Z"
    }
  ],
  "links": { "first": "...", "last": "...", "prev": null, "next": "..." },
  "meta": { "current_page": 1, "per_page": 50, "total": 1 }
}

שדות

שדהסוגתיאור
idintמזהה רשומת היומן.
shipment_idstring | נעדרה-UUID של המשלוח הקשור. קיים רק כאשר יחס ה-shipping נטען.
shipping_methodstring | nullחברת השילוח / שיטת המשלוח שה-SMS קשור אליה.
phonestringטלפון היעד.
messagestringגוף ההודעה שנשלחה.
successboolהאם השליחה הצליחה.
statestring | nullמצב delivery פנימי.
providerobjectתוצאת הספק: status ו-message.
created_atstringחותמת זמן היומן.
updated_atstringחותמת זמן עדכון.

שדות פנימיים (payloads גולמיים של בקשה/תגובה מהספק, מפתחות זרים פנימיים, חותמת זמן soft-delete) אינם חלק מהחוזה הציבורי.

שגיאות

סטטוסקודמתי
401unauthenticatedclient credentials חסרים או שגויים.

GET /notifications/sms-templates

מציג את כל תבניות ה-SMS השייכות לחשבון הקורא. אימות: client credentials.

פרמטרים

אין.

בקשה לדוגמה

bash
curl --location 'https://app.shipos.co.il/api/v2/notifications/sms-templates' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch(
  'https://app.shipos.co.il/api/v2/notifications/sms-templates',
  {
    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: templates } = await response.json()

for (const template of templates) {
  console.log(template.id, template.shipping_method, template.active)
}
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',
    ],
]);

$templates = json_decode(
    $client->get('notifications/sms-templates')->getBody()->getContents(),
    true,
)['data'];

foreach ($templates as $template) {
    echo $template['id'], ' ', $template['shipping_method'], ' ',
        var_export($template['active'], true), PHP_EOL;
}
php
<?php

use Illuminate\Support\Facades\Http;

$templates = 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/notifications/sms-templates')
    ->throw()
    ->json('data');

foreach ($templates as $template) {
    logger()->info($template['shipping_method'], ['active' => $template['active']]);
}
python
# pip install httpx
import os

import httpx

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

for template in templates:
    print(template["id"], template["shipping_method"], template["active"])
go
package main

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

type smsTemplatesResponse struct {
	Data []struct {
		ID             int    `json:"id"`
		ShippingMethod string `json:"shipping_method"`
		Active         bool   `json:"active"`
	} `json:"data"`
}

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

	for _, template := range payload.Data {
		fmt.Println(template.ID, template.ShippingMethod, template.Active)
	}
}
java
// 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 ShipOsSmsTemplates {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/notifications/sms-templates"))
            .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
    }
}
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>("notifications/sms-templates")
    ?? throw new InvalidOperationException("Empty response");

foreach (var template in payload.RootElement.GetProperty("data").EnumerateArray())
{
    Console.WriteLine($"{template.GetProperty("id").GetInt32()} " +
        $"{template.GetProperty("shipping_method").GetString()} " +
        $"{template.GetProperty("active").GetBoolean()}");
}
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/notifications/sms-templates")
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)

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

templates.each do |template|
  puts "#{template["id"]} #{template["shipping_method"]} #{template["active"]}"
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/notifications/sms-templates")
        .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(templates) = payload["data"].as_array() {
        for template in templates {
            println!(
                "{} {} {}",
                template["id"], template["shipping_method"], template["active"]
            );
        }
    }
    Ok(())
}

תגובה 200

json
{
  "data": [
    {
      "id": 15,
      "shipping_method": "hfd",
      "delivery_type": "delivered",
      "message": "היי {name}, ההזמנה שלך הגיעה.",
      "active": true,
      "created_at": "2026-05-01T00:00:00.000000Z",
      "updated_at": "2026-07-10T00:00:00.000000Z"
    }
  ]
}

שדות

שדהסוגתיאור
idintמזהה התבנית (משמש כפרמטר הנתיב {template} בהמשך).
shipping_methodstringחברת השילוח / שיטת המשלוח שהתבנית חלה עליה.
delivery_typestring | nullשלב המסירה שעבורו התבנית מופעלת.
messagestringגוף התבנית.
activeboolהאם התבנית מופעלת (ממופה ל-status במודל).
created_atstringחותמת זמן יצירה.
updated_atstringחותמת זמן עדכון.

שגיאות

סטטוסקודמתי
401unauthenticatedclient credentials חסרים או שגויים.

POST /notifications/sms-templates

יוצר או מעדכן תבנית SMS עבור חשבון הקורא (upsert). מחזיר 201. אימות: client credentials.

פרמטרים

Body

שדהסוגחובהתיאור
shipping_methodstringכןחברת השילוח / שיטת המשלוח שהתבנית חלה עליה. עד 64 תווים.
messagestringכןגוף התבנית. עד 1000 תווים.

בקשה לדוגמה

bash
curl --location --request POST 'https://app.shipos.co.il/api/v2/notifications/sms-templates' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
  "shipping_method": "hfd",
  "message": "היי {name}, ההזמנה שלך הגיעה."
}'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch(
  'https://app.shipos.co.il/api/v2/notifications/sms-templates',
  {
    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({
      shipping_method: 'hfd',
      message: 'היי {name}, ההזמנה שלך הגיעה.',
    }),
  },
)

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

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

console.log(template.id, template.shipping_method, template.active)
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->post('notifications/sms-templates', [
    'json' => [
        'shipping_method' => 'hfd',
        'message' => 'היי {name}, ההזמנה שלך הגיעה.',
    ],
]);

$template = json_decode($response->getBody()->getContents(), true)['data'];

echo $template['id'], ' ', $template['shipping_method'], PHP_EOL;
php
<?php

use Illuminate\Support\Facades\Http;

$template = 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/notifications/sms-templates', [
        'shipping_method' => 'hfd',
        'message' => 'היי {name}, ההזמנה שלך הגיעה.',
    ])
    ->throw()
    ->json('data');

logger()->info('Template upserted', ['id' => $template['id']]);
python
# pip install httpx
import os

import httpx

response = httpx.post(
    "https://app.shipos.co.il/api/v2/notifications/sms-templates",
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
    json={
        "shipping_method": "hfd",
        "message": "היי {name}, ההזמנה שלך הגיעה.",
    },
)
response.raise_for_status()
template = response.json()["data"]

print(template["id"], template["shipping_method"], template["active"])
go
package main

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

func main() {
	body, _ := json.Marshal(map[string]string{
		"shipping_method": "hfd",
		"message":         "היי {name}, ההזמנה שלך הגיעה.",
	})

	req, _ := http.NewRequest("POST",
		"https://app.shipos.co.il/api/v2/notifications/sms-templates",
		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()

	var payload struct {
		Data struct {
			ID             int    `json:"id"`
			ShippingMethod string `json:"shipping_method"`
			Active         bool   `json:"active"`
		} `json:"data"`
	}
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	fmt.Println(payload.Data.ID, payload.Data.ShippingMethod, payload.Data.Active)
}
java
// 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 ShipOsCreateSmsTemplate {
    public static void main(String[] args) throws Exception {
        String body = """
            {"shipping_method":"hfd","message":"היי {name}, ההזמנה שלך הגיעה."}
            """;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/notifications/sms-templates"))
            .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() != 201) {
            throw new RuntimeException("ShipOS error: " + response.body());
        }

        System.out.println(response.body()); // {"data":{...}} — למפו עם Jackson/Gson
    }
}
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 response = await http.PostAsJsonAsync("notifications/sms-templates", new
{
    shipping_method = "hfd",
    message = "היי {name}, ההזמנה שלך הגיעה.",
});
response.EnsureSuccessStatusCode();

var payload = await response.Content.ReadFromJsonAsync<JsonDocument>()
    ?? throw new InvalidOperationException("Empty response");
var template = payload.RootElement.GetProperty("data");

Console.WriteLine($"{template.GetProperty("id").GetInt32()} " +
    $"{template.GetProperty("shipping_method").GetString()}");
ruby
require "net/http"
require "json"

uri = URI("https://app.shipos.co.il/api/v2/notifications/sms-templates")
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({
  shipping_method: "hfd",
  message: "היי {name}, ההזמנה שלך הגיעה.",
})

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)

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

puts "#{template["id"]} #{template["shipping_method"]} #{template["active"]}"
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()
        .post("https://app.shipos.co.il/api/v2/notifications/sms-templates")
        .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(&serde_json::json!({
            "shipping_method": "hfd",
            "message": "היי {name}, ההזמנה שלך הגיעה.",
        }))
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;

    let template = &payload["data"];
    println!("{} {}", template["id"], template["shipping_method"]);
    Ok(())
}

תגובה 201

json
{
  "data": {
    "id": 15,
    "shipping_method": "hfd",
    "delivery_type": "delivered",
    "message": "היי {name}, ההזמנה שלך הגיעה.",
    "active": true,
    "created_at": "2026-07-29T10:00:00.000000Z",
    "updated_at": "2026-07-29T10:00:00.000000Z"
  }
}

שגיאות

סטטוסקודמתי
401unauthenticatedclient credentials חסרים או שגויים.
422validation_failedshipping_method או message חסרים או ארוכים מדי.

PUT /notifications/sms-templates/{template}/toggle

הופך את מצב ההפעלה של תבנית (active). אימות: client credentials.

פרמטרים

Path

שדהסוגחובהתיאור
templateintכןה-id של התבנית.

בקשה לדוגמה

bash
curl --location --request PUT 'https://app.shipos.co.il/api/v2/notifications/sms-templates/15/toggle' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const templateId = 15

const response = await fetch(
  `https://app.shipos.co.il/api/v2/notifications/sms-templates/${templateId}/toggle`,
  {
    method: 'PUT',
    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: template } = await response.json()

console.log(template.id, template.active)
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',
    ],
]);

$templateId = 15;

$template = json_decode(
    $client->put("notifications/sms-templates/{$templateId}/toggle")
        ->getBody()->getContents(),
    true,
)['data'];

echo $template['id'], ' active: ', var_export($template['active'], true), PHP_EOL;
php
<?php

use Illuminate\Support\Facades\Http;

$templateId = 15;

$template = Http::withHeaders([
    'X-Client-Id' => config('services.shipos.client_id'),
    'X-Client-Secret' => config('services.shipos.client_secret'),
])
    ->acceptJson()
    ->put("https://app.shipos.co.il/api/v2/notifications/sms-templates/{$templateId}/toggle")
    ->throw()
    ->json('data');

logger()->info('Template toggled', ['active' => $template['active']]);
python
# pip install httpx
import os

import httpx

template_id = 15

response = httpx.put(
    f"https://app.shipos.co.il/api/v2/notifications/sms-templates/{template_id}/toggle",
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
)
response.raise_for_status()
template = response.json()["data"]

print(template["id"], template["active"])
go
package main

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

func main() {
	templateID := 15

	req, _ := http.NewRequest("PUT", fmt.Sprintf(
		"https://app.shipos.co.il/api/v2/notifications/sms-templates/%d/toggle",
		templateID), 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 struct {
		Data struct {
			ID     int  `json:"id"`
			Active bool `json:"active"`
		} `json:"data"`
	}
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	fmt.Println(payload.Data.ID, payload.Data.Active)
}
java
// 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 ShipOsToggleSmsTemplate {
    public static void main(String[] args) throws Exception {
        int templateId = 15;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/notifications/sms-templates/"
                + templateId + "/toggle"))
            .header("X-Client-Id", System.getenv("SHIPOS_CLIENT_ID"))
            .header("X-Client-Secret", System.getenv("SHIPOS_CLIENT_SECRET"))
            .header("Accept", "application/json")
            .PUT(HttpRequest.BodyPublishers.noBody())
            .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
    }
}
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 templateId = 15;

var response = await http.PutAsync($"notifications/sms-templates/{templateId}/toggle", null);
response.EnsureSuccessStatusCode();

var payload = await response.Content.ReadFromJsonAsync<JsonDocument>()
    ?? throw new InvalidOperationException("Empty response");
var template = payload.RootElement.GetProperty("data");

Console.WriteLine($"{template.GetProperty("id").GetInt32()} " +
    $"{template.GetProperty("active").GetBoolean()}");
ruby
require "net/http"
require "json"

template_id = 15

uri = URI("https://app.shipos.co.il/api/v2/notifications/sms-templates/#{template_id}/toggle")
request = Net::HTTP::Put.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)

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

puts "#{template["id"]} active: #{template["active"]}"
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 template_id = 15;

    let payload: Value = reqwest::Client::new()
        .put(format!(
            "https://app.shipos.co.il/api/v2/notifications/sms-templates/{template_id}/toggle"
        ))
        .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 template = &payload["data"];
    println!("{} {}", template["id"], template["active"]);
    Ok(())
}

תגובה 200

json
{
  "data": {
    "id": 15,
    "shipping_method": "hfd",
    "delivery_type": "delivered",
    "message": "היי {name}, ההזמנה שלך הגיעה.",
    "active": false,
    "created_at": "2026-05-01T00:00:00.000000Z",
    "updated_at": "2026-07-29T10:05:00.000000Z"
  }
}

שגיאות

סטטוסקודמתי
401unauthenticatedclient credentials חסרים או שגויים.
404not_foundאין תבנית עם ה-id הזה השייכת לחשבון הקורא.

DELETE /notifications/sms-templates/

מוחק תבנית שבבעלות חשבון הקורא. אימות: client credentials.

פרמטרים

Path

שדהסוגחובהתיאור
templateintכןה-id של התבנית.

בקשה לדוגמה

bash
curl --location --request DELETE 'https://app.shipos.co.il/api/v2/notifications/sms-templates/15' \
--header 'X-Client-Id: {client_id}' \
--header 'X-Client-Secret: {client_secret}' \
--header 'Accept: application/json'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const templateId = 15

const response = await fetch(
  `https://app.shipos.co.il/api/v2/notifications/sms-templates/${templateId}`,
  {
    method: 'DELETE',
    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 } = await response.json()

console.log(data.deleted)
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',
    ],
]);

$templateId = 15;

$result = json_decode(
    $client->delete("notifications/sms-templates/{$templateId}")
        ->getBody()->getContents(),
    true,
)['data'];

echo var_export($result['deleted'], true), PHP_EOL;
php
<?php

use Illuminate\Support\Facades\Http;

$templateId = 15;

$result = Http::withHeaders([
    'X-Client-Id' => config('services.shipos.client_id'),
    'X-Client-Secret' => config('services.shipos.client_secret'),
])
    ->acceptJson()
    ->delete("https://app.shipos.co.il/api/v2/notifications/sms-templates/{$templateId}")
    ->throw()
    ->json('data');

logger()->info('Template deleted', ['deleted' => $result['deleted']]);
python
# pip install httpx
import os

import httpx

template_id = 15

response = httpx.delete(
    f"https://app.shipos.co.il/api/v2/notifications/sms-templates/{template_id}",
    headers={
        "X-Client-Id": os.environ["SHIPOS_CLIENT_ID"],
        "X-Client-Secret": os.environ["SHIPOS_CLIENT_SECRET"],
        "Accept": "application/json",
    },
)
response.raise_for_status()

print(response.json()["data"]["deleted"])
go
package main

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

func main() {
	templateID := 15

	req, _ := http.NewRequest("DELETE", fmt.Sprintf(
		"https://app.shipos.co.il/api/v2/notifications/sms-templates/%d",
		templateID), 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 struct {
		Data struct {
			Deleted bool `json:"deleted"`
		} `json:"data"`
	}
	if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
		panic(err)
	}

	fmt.Println(payload.Data.Deleted)
}
java
// 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 ShipOsDeleteSmsTemplate {
    public static void main(String[] args) throws Exception {
        int templateId = 15;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.shipos.co.il/api/v2/notifications/sms-templates/"
                + templateId))
            .header("X-Client-Id", System.getenv("SHIPOS_CLIENT_ID"))
            .header("X-Client-Secret", System.getenv("SHIPOS_CLIENT_SECRET"))
            .header("Accept", "application/json")
            .DELETE()
            .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":{"deleted":true}}
    }
}
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 templateId = 15;

var response = await http.DeleteAsync($"notifications/sms-templates/{templateId}");
response.EnsureSuccessStatusCode();

var payload = await response.Content.ReadFromJsonAsync<JsonDocument>()
    ?? throw new InvalidOperationException("Empty response");

Console.WriteLine(payload.RootElement.GetProperty("data")
    .GetProperty("deleted").GetBoolean());
ruby
require "net/http"
require "json"

template_id = 15

uri = URI("https://app.shipos.co.il/api/v2/notifications/sms-templates/#{template_id}")
request = Net::HTTP::Delete.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)

puts JSON.parse(response.body).dig("data", "deleted")
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 template_id = 15;

    let payload: Value = reqwest::Client::new()
        .delete(format!(
            "https://app.shipos.co.il/api/v2/notifications/sms-templates/{template_id}"
        ))
        .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?;

    println!("{}", payload["data"]["deleted"]);
    Ok(())
}

תגובה 200

json
{ "data": { "deleted": true } }

שגיאות

סטטוסקודמתי
401unauthenticatedclient credentials חסרים או שגויים.
404not_foundאין תבנית עם ה-id הזה השייכת לחשבון הקורא.