יתרה
מדווחת כמה יתרה נשארה בחשבון.
POST https://my.textme.co.il/apibalance בדיקת היתרה שנותרה
פרמטרים
| שם | סוג | תיאור | חובה |
|---|---|---|---|
balance | object | מכיל את כל האלמנטים האחרים. | ✔️ |
user | object | מכיל את אלמנט המשתמש. | ✔️ |
username | string | שם המשתמש של החשבון שבו אתם מזוהים במערכת. | ✔️ |
type | string | שלחו mail כדי לקרוא את יתרת הדואר במקום. השמיטו אותו עבור יתרת ה-SMS. | ➖ |
דוגמת בקשה
<?xml version="1.0" encoding="UTF-8"?>
<balance>
<user>
<username>Leeroy</username>
</user>
<type>mail</type>
</balance>{
"balance": {
"user": {
"username": "Leeroy"
},
"type": "mail"
}
}curl --location 'https://my.textme.co.il/api' \
--header "Authorization: Bearer $TEXTME_API_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"balance": {
"user": {
"username": "Leeroy"
},
"type": "mail"
}
}'// 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({
balance: {
user: {
username: 'Leeroy',
},
type: 'mail',
},
}),
})
const result = await response.json()
// גם שגיאה חוזרת כ-HTTP 200, לכן הסטטוס שבגוף התשובה הוא הקובע
if (Number(result.status) !== 0) {
throw new Error(`TextMe ${result.status}: ${result.message}`)
}
console.log(result)<?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' => [
'balance' => [
'user' => [
'username' => 'Leeroy',
],
'type' => 'mail',
],
],
]);
$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
use Illuminate\Support\Facades\Http;
$result = Http::withToken(config('services.textme.token'))
->acceptJson()
->post('https://my.textme.co.il/api', [
'balance' => [
'user' => [
'username' => 'Leeroy',
],
'type' => 'mail',
],
])
->throw()
->json();
// גם שגיאה חוזרת כ-HTTP 200, לכן הסטטוס שבגוף התשובה הוא הקובע
throw_if((int) $result['status'] !== 0, RuntimeException::class,
"TextMe {$result['status']}: {$result['message']}");
logger()->info('TextMe', $result);# 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={
"balance": {
"user": {
"username": "Leeroy",
},
"type": "mail",
},
},
)
response.raise_for_status()
result = response.json()
# גם שגיאה חוזרת כ-HTTP 200, לכן הסטטוס שבגוף התשובה הוא הקובע
if int(result["status"]) != 0:
raise RuntimeError(f"TextMe {result['status']}: {result['message']}")
print(result)package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
payload, _ := json.Marshal(map[string]any{
"balance": map[string]any{
"user": map[string]any{
"username": "Leeroy",
},
"type": "mail",
},
})
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 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 TextMeBalance {
public static void main(String[] args) throws Exception {
String body = """
{
"balance": {
"user": {
"username": "Leeroy"
},
"type": "mail"
}
}
""";
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());
}
}// .NET 8+ using System.Net.Http
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var payload = """
{
"balance": {
"user": {
"username": "Leeroy"
},
"type": "mail"
}
}
""";
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);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({
"balance" => {
"user" => {
"username" => "Leeroy",
},
"type" => "mail",
},
})
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// [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!({
"balance": {
"user": {
"username": "Leeroy"
},
"type": "mail"
}
}))
.send()
.await?
.json()
.await?;
// גם שגיאה חוזרת כ-HTTP 200, לכן הסטטוס שבגוף התשובה הוא הקובע
if result["status"] != 0 {
return Err(format!("TextMe {}: {}", result["status"], result["message"]).into());
}
println!("{result}");
Ok(())
}תשובה
<?xml version="1.0" encoding="UTF-8"?>
<balance>
<status>0</status>
<message>Your balance is : 42 and international balance: 40.5 nis</message>
<balance>42</balance>
<interantional_balance>40.5</interantional_balance>
</balance>{
"status": 0,
"message": "Your balance is : 42 and international balance: 40.5 nis",
"balance": "42",
"international_balance": "40.5"
}| שדה | סוג | תיאור |
|---|---|---|
status | int | 0 בהצלחה. |
message | string | היתרה כמשפט, לדוגמה Your balance is : 42 and international balance: 40.5 nis. |
balance | string | היתרה המקומית שנותרה. |
international_balance | string | היתרה הבינלאומית שנותרה, בשקלים. |
שדה אחד מאוית שונה ב-XML
בתשובת ה-XML הנתון הבינלאומי חוזר כ-<interantional_balance>. שגיאת כתיב שמוטמעת בפורמט עצמו. בתשובת ה-JSON האיות הוא international_balance. התאימו את הקוד לפורמט שאתם באמת מפרסרים, ולא לזה שאתם מצפים לו.
שגיאות
| Status | מתי |
|---|---|
3, 10, 11 | טוקן לא תקף, פג תוקף, או שייך ל-username אחר. |
503 | ה-username אינו חשבון שאתם רשאים לפעול בשמו. |
511 | החשבון אינו רשאי לבצע את הפעולה. |
הערות על השדות
שתי יתרות, שני מטבעות
balance מונה קרדיטים של הודעות מקומיות. international_balance הוא כסף, בשקלים, שנגרע כששולחים ליעדים מחוץ לישראל עם includes_international בערך 1. סיום אחת מהן מייצר סטטוס 4 (Not enough credit) או 12 (Not enough money) בשליחה הבאה. איזה מהם, תלוי ביעד.
בדיקה לפני ריצה גדולה
בדיקה זולה לפני שליחת אצווה גדולה, מכיוון שאצווה שחורגת מהיתרה נכשלת כמכלול ולא באמצע:
const balance = await textme({ balance: { user: { username: 'Leeroy' } } })
if (Number(balance.balance) < recipients.length) {
throw new Error(
`Need ${recipients.length} credits, have ${balance.balance}`,
)
}
await textme({ bulk: { /* … */ } })balance = textme({"balance": {"user": {"username": "Leeroy"}}})
if int(balance["balance"]) < len(recipients):
raise RuntimeError(
f"Need {len(recipients)} credits, have {balance['balance']}"
)
textme({"bulk": {...}})התייחסו לזה כאל שומר סף ולא כאל הבטחה: תהליך אחר על אותו חשבון יכול לנצל את היתרה בין שתי הקריאות. התשובה המחייבת היא עדיין ה-status של השליחה.
יתרות של חשבונות משנה
balance מדווחת על החשבון הקורא בלבד. משווקים קוראים את כל חשבונות המשנה בבת אחת עם getBlanceSubs, ומעבירים אליהם קרדיטים עם updateAmountSub.

