Skip to content

קמפיינים

כל שליחה יוצרת קמפיין. קמפיין מתוזמן אפשר לעצור לפני שהוא יוצא, לפי מזהה או לפי שם. קמפייני יום הולדת — שליחות חוזרות שמופעלות לפי תאריך הלידה של איש קשר — נקראים ונערכים גם הם כאן.

http
POST https://my.textme.co.il/api

cancel ביטול קמפיין לפי מזהה

מבטלת קמפיין מתוזמן אחד.

פרמטרים

שםסוגתיאורחובה
cancelobjectמכיל את כל האלמנטים האחרים.✔️
userobjectמכיל את אלמנט המשתמש.✔️
usernamestringשם המשתמש של החשבון שבו אתם מזוהים במערכת.✔️
campaign_idintהמספר של הקמפיין שלכם.✔️

דוגמת בקשה

xml
<?xml version="1.0" encoding="UTF-8"?>
<cancel>
    <user>
        <username>Leeroy</username>
    </user>
    <campaign_id>1234</campaign_id>
</cancel>
json
{
  "cancel": {
    "user": {
      "username": "Leeroy"
    },
    "campaign_id": "1234"
  }
}
bash
curl --location 'https://my.textme.co.il/api' \
--header "Authorization: Bearer $TEXTME_API_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
  "cancel": {
    "user": {
      "username": "Leeroy"
    },
    "campaign_id": "1234"
  }
}'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch('https://my.textme.co.il/api', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TEXTME_API_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    cancel: {
      user: {
        username: 'Leeroy',
      },
      campaign_id: '1234',
    },
  }),
})

const result = await response.json()

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if (Number(result.status) !== 0) {
  throw new Error(`TextMe ${result.status}: ${result.message}`)
}

console.log(result)
php
<?php
// composer require guzzlehttp/guzzle

$client = new \GuzzleHttp\Client([
    'headers' => [
        'Authorization' => 'Bearer '.getenv('TEXTME_API_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

$response = $client->post('https://my.textme.co.il/api', [
    'json' => [
        'cancel' => [
            'user' => [
                'username' => 'Leeroy',
            ],
            'campaign_id' => '1234',
        ],
    ],
]);

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

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if ((int) $result['status'] !== 0) {
    throw new RuntimeException("TextMe {$result['status']}: {$result['message']}");
}

print_r($result);
php
<?php

use Illuminate\Support\Facades\Http;

$result = Http::withToken(config('services.textme.token'))
    ->acceptJson()
    ->post('https://my.textme.co.il/api', [
        'cancel' => [
            'user' => [
                'username' => 'Leeroy',
            ],
            'campaign_id' => '1234',
        ],
    ])
    ->throw()
    ->json();

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
throw_if((int) $result['status'] !== 0, RuntimeException::class,
    "TextMe {$result['status']}: {$result['message']}");

logger()->info('TextMe', $result);
python
# pip install httpx
import os

import httpx

response = httpx.post(
    "https://my.textme.co.il/api",
    headers={"Authorization": f"Bearer {os.environ['TEXTME_API_TOKEN']}"},
    json={
        "cancel": {
            "user": {
                "username": "Leeroy",
            },
            "campaign_id": "1234",
        },
    },
)
response.raise_for_status()
result = response.json()

# גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if int(result["status"]) != 0:
    raise RuntimeError(f"TextMe {result['status']}: {result['message']}")

print(result)
go
package main

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

func main() {
	payload, _ := json.Marshal(map[string]any{
		"cancel": map[string]any{
			"user": map[string]any{
				"username": "Leeroy",
			},
			"campaign_id": "1234",
		},
	})

	req, _ := http.NewRequest("POST", "https://my.textme.co.il/api", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("TEXTME_API_TOKEN"))
	req.Header.Set("Content-Type", "application/json")

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

	var result struct {
		Status  json.Number `json:"status"`
		Message string      `json:"message"`
	}
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		panic(err)
	}

	// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
	if result.Status.String() != "0" {
		panic(fmt.Sprintf("TextMe %s: %s", result.Status, result.Message))
	}

	fmt.Println(result.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 TextMeCampaignCancelById {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "cancel": {
                "user": {
                  "username": "Leeroy"
                },
                "campaign_id": "1234"
              }
            }
            """;

        HttpRequest request = HttpRequest.newBuilder(URI.create("https://my.textme.co.il/api"))
            .header("Authorization", "Bearer " + System.getenv("TEXTME_API_TOKEN"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

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

        // גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
        System.out.println(response.body());
    }
}
csharp
// .NET 8+ — System.Net.Http
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

var payload = """
    {
      "cancel": {
        "user": {
          "username": "Leeroy"
        },
        "campaign_id": "1234"
      }
    }
    """;

using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("TEXTME_API_TOKEN"));

var response = await http.PostAsync("https://my.textme.co.il/api",
    new StringContent(payload, Encoding.UTF8, "application/json"));

var result = JsonDocument.Parse(await response.Content.ReadAsStringAsync()).RootElement;
var status = result.GetProperty("status").ToString();

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if (status != "0")
{
    var message = result.GetProperty("message").ToString();
    throw new Exception($"TextMe {status}: {message}");
}

Console.WriteLine(result);
ruby
require "net/http"
require "json"

uri = URI("https://my.textme.co.il/api")

request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('TEXTME_API_TOKEN')}"
request["Content-Type"] = "application/json"
request.body = JSON.dump({
  "cancel" => {
    "user" => {
      "username" => "Leeroy",
    },
    "campaign_id" => "1234",
  },
})

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

result = JSON.parse(response.body)

# גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
raise "TextMe #{result['status']}: #{result['message']}" unless result["status"].to_i.zero?

pp result
rust
// [dependencies]
// reqwest = { version = "0.12", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
// serde_json = "1"
use serde_json::{json, Value};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let result: Value = reqwest::Client::new()
        .post("https://my.textme.co.il/api")
        .bearer_auth(std::env::var("TEXTME_API_TOKEN")?)
        .json(&json!({
          "cancel": {
            "user": {
              "username": "Leeroy"
            },
            "campaign_id": "1234"
          }
        }))
        .send()
        .await?
        .json()
        .await?;

    // גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
    if result["status"] != 0 {
        return Err(format!("TextMe {}: {}", result["status"], result["message"]).into());
    }

    println!("{result}");
    Ok(())
}

תשובה

xml
<?xml version="1.0" encoding="UTF-8"?>
<cancel>
    <status>0</status>
    <message>Campaign successfuly cancel</message>
</cancel>
json
{
  "status": 0,
  "message": "Campaign successfuly cancel"
}

שגיאות

Statusמתי
955Campaign already cancel — כבר בוטל. בפועל ללא השפעה; בדרך כלל אפשר להתעלם.
966Campaign already sent — מאוחר מדי.
970Campaigns was not cancelled. Contact support.
977Campaign does not belong to customer or Not exist.

cancel ביטול קמפיינים לפי שם

מבטלת כל קמפיין מתוזמן שה-campaign_name שלו תואם. התשובה מדווחת כמה נפגעו.

פרמטרים

שםסוגתיאורחובה
cancelobjectמכיל את כל האלמנטים האחרים.✔️
userobjectמכיל את אלמנט המשתמש.✔️
usernamestringשם המשתמש של החשבון שבו אתם מזוהים במערכת.✔️
campaign_namestringשם הקמפיין שלכם.✔️

דוגמת בקשה

xml
<?xml version="1.0" encoding="UTF-8"?>
<cancel>
    <user>
        <username>Leeroy</username>
    </user>
    <campaign_name>My Campaign</campaign_name>
</cancel>
json
{
  "cancel": {
    "user": {
      "username": "Leeroy"
    },
    "campaign_name": "My Campaign"
  }
}
bash
curl --location 'https://my.textme.co.il/api' \
--header "Authorization: Bearer $TEXTME_API_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
  "cancel": {
    "user": {
      "username": "Leeroy"
    },
    "campaign_name": "My Campaign"
  }
}'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch('https://my.textme.co.il/api', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TEXTME_API_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    cancel: {
      user: {
        username: 'Leeroy',
      },
      campaign_name: 'My Campaign',
    },
  }),
})

const result = await response.json()

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if (Number(result.status) !== 0) {
  throw new Error(`TextMe ${result.status}: ${result.message}`)
}

console.log(result)
php
<?php
// composer require guzzlehttp/guzzle

$client = new \GuzzleHttp\Client([
    'headers' => [
        'Authorization' => 'Bearer '.getenv('TEXTME_API_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

$response = $client->post('https://my.textme.co.il/api', [
    'json' => [
        'cancel' => [
            'user' => [
                'username' => 'Leeroy',
            ],
            'campaign_name' => 'My Campaign',
        ],
    ],
]);

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

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if ((int) $result['status'] !== 0) {
    throw new RuntimeException("TextMe {$result['status']}: {$result['message']}");
}

print_r($result);
php
<?php

use Illuminate\Support\Facades\Http;

$result = Http::withToken(config('services.textme.token'))
    ->acceptJson()
    ->post('https://my.textme.co.il/api', [
        'cancel' => [
            'user' => [
                'username' => 'Leeroy',
            ],
            'campaign_name' => 'My Campaign',
        ],
    ])
    ->throw()
    ->json();

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
throw_if((int) $result['status'] !== 0, RuntimeException::class,
    "TextMe {$result['status']}: {$result['message']}");

logger()->info('TextMe', $result);
python
# pip install httpx
import os

import httpx

response = httpx.post(
    "https://my.textme.co.il/api",
    headers={"Authorization": f"Bearer {os.environ['TEXTME_API_TOKEN']}"},
    json={
        "cancel": {
            "user": {
                "username": "Leeroy",
            },
            "campaign_name": "My Campaign",
        },
    },
)
response.raise_for_status()
result = response.json()

# גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if int(result["status"]) != 0:
    raise RuntimeError(f"TextMe {result['status']}: {result['message']}")

print(result)
go
package main

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

func main() {
	payload, _ := json.Marshal(map[string]any{
		"cancel": map[string]any{
			"user": map[string]any{
				"username": "Leeroy",
			},
			"campaign_name": "My Campaign",
		},
	})

	req, _ := http.NewRequest("POST", "https://my.textme.co.il/api", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("TEXTME_API_TOKEN"))
	req.Header.Set("Content-Type", "application/json")

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

	var result struct {
		Status  json.Number `json:"status"`
		Message string      `json:"message"`
	}
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		panic(err)
	}

	// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
	if result.Status.String() != "0" {
		panic(fmt.Sprintf("TextMe %s: %s", result.Status, result.Message))
	}

	fmt.Println(result.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 TextMeCampaignCancelByName {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "cancel": {
                "user": {
                  "username": "Leeroy"
                },
                "campaign_name": "My Campaign"
              }
            }
            """;

        HttpRequest request = HttpRequest.newBuilder(URI.create("https://my.textme.co.il/api"))
            .header("Authorization", "Bearer " + System.getenv("TEXTME_API_TOKEN"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

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

        // גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
        System.out.println(response.body());
    }
}
csharp
// .NET 8+ — System.Net.Http
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

var payload = """
    {
      "cancel": {
        "user": {
          "username": "Leeroy"
        },
        "campaign_name": "My Campaign"
      }
    }
    """;

using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("TEXTME_API_TOKEN"));

var response = await http.PostAsync("https://my.textme.co.il/api",
    new StringContent(payload, Encoding.UTF8, "application/json"));

var result = JsonDocument.Parse(await response.Content.ReadAsStringAsync()).RootElement;
var status = result.GetProperty("status").ToString();

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if (status != "0")
{
    var message = result.GetProperty("message").ToString();
    throw new Exception($"TextMe {status}: {message}");
}

Console.WriteLine(result);
ruby
require "net/http"
require "json"

uri = URI("https://my.textme.co.il/api")

request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('TEXTME_API_TOKEN')}"
request["Content-Type"] = "application/json"
request.body = JSON.dump({
  "cancel" => {
    "user" => {
      "username" => "Leeroy",
    },
    "campaign_name" => "My Campaign",
  },
})

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

result = JSON.parse(response.body)

# גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
raise "TextMe #{result['status']}: #{result['message']}" unless result["status"].to_i.zero?

pp result
rust
// [dependencies]
// reqwest = { version = "0.12", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
// serde_json = "1"
use serde_json::{json, Value};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let result: Value = reqwest::Client::new()
        .post("https://my.textme.co.il/api")
        .bearer_auth(std::env::var("TEXTME_API_TOKEN")?)
        .json(&json!({
          "cancel": {
            "user": {
              "username": "Leeroy"
            },
            "campaign_name": "My Campaign"
          }
        }))
        .send()
        .await?
        .json()
        .await?;

    // גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
    if result["status"] != 0 {
        return Err(format!("TextMe {}: {}", result["status"], result["message"]).into());
    }

    println!("{result}");
    Ok(())
}

תשובה

xml
<?xml version="1.0" encoding="UTF-8"?>
<cancel>
    <status>0</status>
    <message>Campaigns successfully cancel</message>
    <count>1</count>
</cancel>
json
{
  "status": 0,
  "message": "Campaigns successfully cancel",
  "count": 1
}
שדהסוגתיאור
statusint0 בהצלחה.
messagestringCampaigns successfully cancel.
countintכמה קמפיינים בוטלו.

התאמת השם היא כל בוחר היעד

אין שלב אישור ואין הרצה יבשה. כל קמפיין ממתין שנושא את השם הזה מבוטל — ובדיוק בשל כך פיצול ריצת bulk גדולה לכמה קריאות עם campaign_name משותף הוא רעיון טוב: בקשה אחת עוצרת את כל הריצה.

המשמעות הנגדית היא ששם כללי כמו newsletter יבטל יום אחד יותר ממה שהתכוונתם. הפכו את השמות לייחודיים לכל ריצה — newsletter-2026-08-17 ולא newsletter.

שגיאות

כמו בביטול לפי מזהה, עם count בערך 0 ו-status בערך 0 כשלא נמצאה התאמה.

get_birthday_campaigns רשימת קמפייני יום הולדת

פרמטרים

שםסוגתיאורחובה
get_birthday_campaignsobjectמכיל את כל האלמנטים האחרים.✔️
userobjectמכיל את אלמנט המשתמש.✔️
usernamestringשם המשתמש של החשבון שבו אתם מזוהים במערכת.✔️

דוגמת בקשה

xml
<?xml version="1.0" encoding="UTF-8"?>
<get_birthday_campaigns>
    <user>
        <username>XXXXXX</username>
    </user>
</get_birthday_campaigns>
json
{
  "get_birthday_campaigns": {
    "user": {
      "username": "XXXXXX"
    }
  }
}
bash
curl --location 'https://my.textme.co.il/api' \
--header "Authorization: Bearer $TEXTME_API_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
  "get_birthday_campaigns": {
    "user": {
      "username": "XXXXXX"
    }
  }
}'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch('https://my.textme.co.il/api', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TEXTME_API_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    get_birthday_campaigns: {
      user: {
        username: 'XXXXXX',
      },
    },
  }),
})

const result = await response.json()

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if (Number(result.status) !== 0) {
  throw new Error(`TextMe ${result.status}: ${result.message}`)
}

console.log(result)
php
<?php
// composer require guzzlehttp/guzzle

$client = new \GuzzleHttp\Client([
    'headers' => [
        'Authorization' => 'Bearer '.getenv('TEXTME_API_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

$response = $client->post('https://my.textme.co.il/api', [
    'json' => [
        'get_birthday_campaigns' => [
            'user' => [
                'username' => 'XXXXXX',
            ],
        ],
    ],
]);

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

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if ((int) $result['status'] !== 0) {
    throw new RuntimeException("TextMe {$result['status']}: {$result['message']}");
}

print_r($result);
php
<?php

use Illuminate\Support\Facades\Http;

$result = Http::withToken(config('services.textme.token'))
    ->acceptJson()
    ->post('https://my.textme.co.il/api', [
        'get_birthday_campaigns' => [
            'user' => [
                'username' => 'XXXXXX',
            ],
        ],
    ])
    ->throw()
    ->json();

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
throw_if((int) $result['status'] !== 0, RuntimeException::class,
    "TextMe {$result['status']}: {$result['message']}");

logger()->info('TextMe', $result);
python
# pip install httpx
import os

import httpx

response = httpx.post(
    "https://my.textme.co.il/api",
    headers={"Authorization": f"Bearer {os.environ['TEXTME_API_TOKEN']}"},
    json={
        "get_birthday_campaigns": {
            "user": {
                "username": "XXXXXX",
            },
        },
    },
)
response.raise_for_status()
result = response.json()

# גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if int(result["status"]) != 0:
    raise RuntimeError(f"TextMe {result['status']}: {result['message']}")

print(result)
go
package main

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

func main() {
	payload, _ := json.Marshal(map[string]any{
		"get_birthday_campaigns": map[string]any{
			"user": map[string]any{
				"username": "XXXXXX",
			},
		},
	})

	req, _ := http.NewRequest("POST", "https://my.textme.co.il/api", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("TEXTME_API_TOKEN"))
	req.Header.Set("Content-Type", "application/json")

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

	var result struct {
		Status  json.Number `json:"status"`
		Message string      `json:"message"`
	}
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		panic(err)
	}

	// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
	if result.Status.String() != "0" {
		panic(fmt.Sprintf("TextMe %s: %s", result.Status, result.Message))
	}

	fmt.Println(result.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 TextMeBirthdayList {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "get_birthday_campaigns": {
                "user": {
                  "username": "XXXXXX"
                }
              }
            }
            """;

        HttpRequest request = HttpRequest.newBuilder(URI.create("https://my.textme.co.il/api"))
            .header("Authorization", "Bearer " + System.getenv("TEXTME_API_TOKEN"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

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

        // גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
        System.out.println(response.body());
    }
}
csharp
// .NET 8+ — System.Net.Http
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

var payload = """
    {
      "get_birthday_campaigns": {
        "user": {
          "username": "XXXXXX"
        }
      }
    }
    """;

using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("TEXTME_API_TOKEN"));

var response = await http.PostAsync("https://my.textme.co.il/api",
    new StringContent(payload, Encoding.UTF8, "application/json"));

var result = JsonDocument.Parse(await response.Content.ReadAsStringAsync()).RootElement;
var status = result.GetProperty("status").ToString();

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if (status != "0")
{
    var message = result.GetProperty("message").ToString();
    throw new Exception($"TextMe {status}: {message}");
}

Console.WriteLine(result);
ruby
require "net/http"
require "json"

uri = URI("https://my.textme.co.il/api")

request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('TEXTME_API_TOKEN')}"
request["Content-Type"] = "application/json"
request.body = JSON.dump({
  "get_birthday_campaigns" => {
    "user" => {
      "username" => "XXXXXX",
    },
  },
})

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

result = JSON.parse(response.body)

# גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
raise "TextMe #{result['status']}: #{result['message']}" unless result["status"].to_i.zero?

pp result
rust
// [dependencies]
// reqwest = { version = "0.12", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
// serde_json = "1"
use serde_json::{json, Value};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let result: Value = reqwest::Client::new()
        .post("https://my.textme.co.il/api")
        .bearer_auth(std::env::var("TEXTME_API_TOKEN")?)
        .json(&json!({
          "get_birthday_campaigns": {
            "user": {
              "username": "XXXXXX"
            }
          }
        }))
        .send()
        .await?
        .json()
        .await?;

    // גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
    if result["status"] != 0 {
        return Err(format!("TextMe {}: {}", result["status"], result["message"]).into());
    }

    println!("{result}");
    Ok(())
}

תשובה

xml
<?xml version="1.0" encoding="utf-8"?>
<sms>
    <status>0</status>
    <message></message>
    <birthday_campaigns>
        <birthday_campaign>
            <CAMPAIGN_ID>XXXX</CAMPAIGN_ID>
            <CAMPAIGN_NAME>XXXX</CAMPAIGN_NAME>
            <CREATED_ON>18/10/23 14:40:39</CREATED_ON>
            <ACTIVE_DESTINATIONS>X</ACTIVE_DESTINATIONS>
        </birthday_campaign>
    </birthday_campaigns>
</sms>
json
{
  "status": 0,
  "message": "",
  "birthday_campaigns": {
    "birthday_campaign": [
      {
        "CAMPAIGN_ID": "xxxxx",
        "CAMPAIGN_NAME": "xxxxx",
        "CREATED_ON": "18/10/23 14:40:39",
        "ACTIVE_DESTINATIONS": ""
      }
    ]
  }
}
שדהסוגתיאור
birthday_campaigns.birthday_campaignarrayרשומה אחת לכל קמפיין.
CAMPAIGN_IDstringמזהה הקמפיין — מה ש-edit_birthday_campaign צריך.
CAMPAIGN_NAMEstringשמו.
CREATED_ONstringמועד היצירה, dd/mm/yy hh:mm:ss.
ACTIVE_DESTINATIONSstringכמה אנשי קשר הוא מכוון אליהם כרגע.

שמות השדות כאן באותיות גדולות

בשונה משאר ה-API, שדות של קמפייני יום הולדת חוזרים כ-CAMPAIGN_ID, CAMPAIGN_NAME וכן הלאה. פרסרים שרגישים לאותיות גדולות וקטנות צריכים לצפות לזה.

שגיאות

Statusמתי
3, 10, 11טוקן לא תקף, פג תוקף, או שייך ל-username אחר.
511החשבון אינו רשאי לבצע את הפעולה.

edit_birthday_campaign שינוי ההודעה

מחליפה את גוף ההודעה של קמפיין יום הולדת קיים. התזמון, הקהל והשם של הקמפיין נשארים כפי שהם.

פרמטרים

שםסוגתיאורחובה
edit_birthday_campaignobjectמכיל את כל האלמנטים האחרים.✔️
userobjectמכיל את אלמנט המשתמש.✔️
usernamestringשם המשתמש של החשבון שבו אתם מזוהים במערכת.✔️
campaign_idobjectה-campaign_id שברצונכם לערוך.✔️
messageobjectתוכן ההודעה החדשה.✔️

דוגמת בקשה

xml
<?xml version="1.0" encoding="UTF-8"?>
<edit_birthday_campaign>
    <user>
        <username>XXXX</username>
    </user>
    <campaign_id>XXXX</campaign_id>
    <message>XXXX</message>
</edit_birthday_campaign>
json
{
  "edit_birthday_campaign": {
    "user": {
      "username": "XXXX"
    },
    "campaign_id": "XXXX",
    "message": "XXXX"
  }
}
bash
curl --location 'https://my.textme.co.il/api' \
--header "Authorization: Bearer $TEXTME_API_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
  "edit_birthday_campaign": {
    "user": {
      "username": "XXXX"
    },
    "campaign_id": "XXXX",
    "message": "XXXX"
  }
}'
js
// Node.js 18+ / דפדפנים — ללא תלויות
const response = await fetch('https://my.textme.co.il/api', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TEXTME_API_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    edit_birthday_campaign: {
      user: {
        username: 'XXXX',
      },
      campaign_id: 'XXXX',
      message: 'XXXX',
    },
  }),
})

const result = await response.json()

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if (Number(result.status) !== 0) {
  throw new Error(`TextMe ${result.status}: ${result.message}`)
}

console.log(result)
php
<?php
// composer require guzzlehttp/guzzle

$client = new \GuzzleHttp\Client([
    'headers' => [
        'Authorization' => 'Bearer '.getenv('TEXTME_API_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

$response = $client->post('https://my.textme.co.il/api', [
    'json' => [
        'edit_birthday_campaign' => [
            'user' => [
                'username' => 'XXXX',
            ],
            'campaign_id' => 'XXXX',
            'message' => 'XXXX',
        ],
    ],
]);

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

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if ((int) $result['status'] !== 0) {
    throw new RuntimeException("TextMe {$result['status']}: {$result['message']}");
}

print_r($result);
php
<?php

use Illuminate\Support\Facades\Http;

$result = Http::withToken(config('services.textme.token'))
    ->acceptJson()
    ->post('https://my.textme.co.il/api', [
        'edit_birthday_campaign' => [
            'user' => [
                'username' => 'XXXX',
            ],
            'campaign_id' => 'XXXX',
            'message' => 'XXXX',
        ],
    ])
    ->throw()
    ->json();

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
throw_if((int) $result['status'] !== 0, RuntimeException::class,
    "TextMe {$result['status']}: {$result['message']}");

logger()->info('TextMe', $result);
python
# pip install httpx
import os

import httpx

response = httpx.post(
    "https://my.textme.co.il/api",
    headers={"Authorization": f"Bearer {os.environ['TEXTME_API_TOKEN']}"},
    json={
        "edit_birthday_campaign": {
            "user": {
                "username": "XXXX",
            },
            "campaign_id": "XXXX",
            "message": "XXXX",
        },
    },
)
response.raise_for_status()
result = response.json()

# גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if int(result["status"]) != 0:
    raise RuntimeError(f"TextMe {result['status']}: {result['message']}")

print(result)
go
package main

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

func main() {
	payload, _ := json.Marshal(map[string]any{
		"edit_birthday_campaign": map[string]any{
			"user": map[string]any{
				"username": "XXXX",
			},
			"campaign_id": "XXXX",
			"message": "XXXX",
		},
	})

	req, _ := http.NewRequest("POST", "https://my.textme.co.il/api", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("TEXTME_API_TOKEN"))
	req.Header.Set("Content-Type", "application/json")

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

	var result struct {
		Status  json.Number `json:"status"`
		Message string      `json:"message"`
	}
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		panic(err)
	}

	// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
	if result.Status.String() != "0" {
		panic(fmt.Sprintf("TextMe %s: %s", result.Status, result.Message))
	}

	fmt.Println(result.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 TextMeBirthdayEdit {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "edit_birthday_campaign": {
                "user": {
                  "username": "XXXX"
                },
                "campaign_id": "XXXX",
                "message": "XXXX"
              }
            }
            """;

        HttpRequest request = HttpRequest.newBuilder(URI.create("https://my.textme.co.il/api"))
            .header("Authorization", "Bearer " + System.getenv("TEXTME_API_TOKEN"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

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

        // גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
        System.out.println(response.body());
    }
}
csharp
// .NET 8+ — System.Net.Http
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

var payload = """
    {
      "edit_birthday_campaign": {
        "user": {
          "username": "XXXX"
        },
        "campaign_id": "XXXX",
        "message": "XXXX"
      }
    }
    """;

using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("TEXTME_API_TOKEN"));

var response = await http.PostAsync("https://my.textme.co.il/api",
    new StringContent(payload, Encoding.UTF8, "application/json"));

var result = JsonDocument.Parse(await response.Content.ReadAsStringAsync()).RootElement;
var status = result.GetProperty("status").ToString();

// גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
if (status != "0")
{
    var message = result.GetProperty("message").ToString();
    throw new Exception($"TextMe {status}: {message}");
}

Console.WriteLine(result);
ruby
require "net/http"
require "json"

uri = URI("https://my.textme.co.il/api")

request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('TEXTME_API_TOKEN')}"
request["Content-Type"] = "application/json"
request.body = JSON.dump({
  "edit_birthday_campaign" => {
    "user" => {
      "username" => "XXXX",
    },
    "campaign_id" => "XXXX",
    "message" => "XXXX",
  },
})

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

result = JSON.parse(response.body)

# גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
raise "TextMe #{result['status']}: #{result['message']}" unless result["status"].to_i.zero?

pp result
rust
// [dependencies]
// reqwest = { version = "0.12", features = ["json"] }
// tokio = { version = "1", features = ["full"] }
// serde_json = "1"
use serde_json::{json, Value};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let result: Value = reqwest::Client::new()
        .post("https://my.textme.co.il/api")
        .bearer_auth(std::env::var("TEXTME_API_TOKEN")?)
        .json(&json!({
          "edit_birthday_campaign": {
            "user": {
              "username": "XXXX"
            },
            "campaign_id": "XXXX",
            "message": "XXXX"
          }
        }))
        .send()
        .await?
        .json()
        .await?;

    // גם שגיאה חוזרת כ-HTTP 200 — הסטטוס שבגוף התשובה הוא הקובע
    if result["status"] != 0 {
        return Err(format!("TextMe {}: {}", result["status"], result["message"]).into());
    }

    println!("{result}");
    Ok(())
}

תשובה

xml
<?xml version="1.0" encoding="utf-8"?>
<sms>
    <status>0</status>
    <message>birthday campaign successfully updated</message>
</sms>
json
{
  "status": 0,
  "message": "birthday campaign successfully updated"
}

שגיאות

Statusמתי
977הקמפיין אינו קיים, או שהוא שייך לחשבון אחר.
989ההודעה החדשה ריקה או עוברת 1005 תווים.
511החשבון אינו רשאי לבצע את הפעולה.

הערות על השדות

מה אפשר לבטל ומה לא

הביטול מגיע רק לקמפיינים שלא יצאו. שליחה בלי timing נשלחת מיד ועוברת את נקודת הביטול עוד לפני שהספקתם לקרוא — 966. תזמון עם timing הוא מה שקונה לכם את החלון.

איזו ידית לשמור?

שליחה מחזירה shipment_id; הביטול מקבל campaign_id. בפועל שניהם מתייחסים לאותו קמפיין, וההרגל העמיד יותר הוא להגדיר campaign_name ייחודי בכל שליחה ולבטל לפי שם — זה עובד גם על ריצה שפוצלה לכמה קריאות, וזה לא תלוי בכך ששמרתם מזהה.

קמפייני יום הולדת נוצרים בממשק הניהול

ה-API מציג אותם ומחליף את ההודעה שלהם. יצירה של קמפיין, קביעת התזמון שלו או בחירת הקהל שלו הן פעולות בממשק הניהול.