---
url: https://textme-docs.matat.io/reference/soap.md
description: >-
  The SOAP interface: the objects, the four methods, how its window limits
  differ from /api, and PHP and Java client examples.
---

# SOAP API

Alongside the [XML/JSON endpoint](../guide/request-format.md), TextMe exposes a SOAP service covering four operations: send, bulk send, delivery reports and sender verification.

```http
WSDL     https://my.textme.co.il/soap?wsdl
SOAPAction  https://my.textme.co.il/soap/
```

Authentication is the same bearer token as the REST-style endpoint, sent as an `Authorization` MIME header on the SOAP message.

::: tip Which interface should you use?
The SOAP service covers four operations; the `/api` endpoint covers all twenty-plus, including contact lists, blocklists, campaigns and sub-accounts. Choose SOAP only when a generated client is genuinely easier for your stack. Otherwise the [main endpoint](../endpoints/overview.md) is the fuller surface.
:::

## Objects

### `Response`

Returned by `sendSms` and `sendBulkSms`.

```java
public class Response {
    int status;
    String message;
}
```

`status` follows the same scale as everywhere else: `0` is success, anything else is a [status code](./status-codes.md). `message` explains it. Empty on a clean request.

### `Phone`

One destination.

```java
public class Phone {
    int phone;
    String id;
}
```

| Field | Required | Description |
|---|---|---|
| `phone` | yes | The destination number, e.g. `50xxxxxxx`. |
| `id` | no | Your own external id for this destination. Supply a unique one per destination if you intend to pull delivery reports for it later. |

### `Sms`

One message and its destinations.

```java
public class Sms {
    List<Phone> destinations;
    String message;
    String timing;
    String source;
}
```

| Field | Required | Description |
|---|---|---|
| `destinations` | yes | At least one `Phone`. |
| `message` | yes | The message body. |
| `source` | yes | The sender that will appear on the handset. |
| `timing` | no | Send in the future, formatted `dd/mm/yy hh:ss`. Ignored inside `sendBulkSms`. |

### `Messages`

A batch of messages, used by `sendBulkSms`.

```java
public class Messages {
    List<Sms> sms;
}
```

At least one `Sms` is required.

### `DlrRequest`

The query sent to `getDlrReport`.

```java
public class DlrRequest {
    List<String> id;
    String from;
    String to;
}
```

| Field | Required | Description |
|---|---|---|
| `id` | yes | The external ids supplied on the `Phone` objects when sending. |
| `from` | yes | Start of the window, `dd/mm/yy hh:ss`. |
| `to` | yes | End of the window, same format. |

### `Dlr`

One delivery report. Read-only. You never populate it.

```java
public class Dlr {
    String id;
    String status;
    String heMessage;
    String enMessage;
    String date;
    int phone;
}
```

| Field | Description |
|---|---|
| `id` | The external id supplied when the message was sent. |
| `status` | The delivery status. See [DLR statuses](./dlr-statuses.md). |
| `heMessage` | The status in Hebrew. |
| `enMessage` | The status in English. |
| `date` | When the status was recorded, `dd/mm/yy hh:ss`. |
| `phone` | The destination the message went to. |

### `DlrResponse`

What `getDlrReport` returns.

```java
public class DlrResponse {
    int status;
    String message;
    List<Dlr> dlrs;
}
```

`status` `0` means the report was produced. It says nothing about whether the messages arrived. That is what each `Dlr.status` is for.

## Methods

### `sendSms`

Sends one message to one or more destinations. Use it when everybody receives the *same* text.

```java
Response r = sendSms("username", sms);
```

```xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:soap="https://my.textme.co.il/soap">
    <soapenv:Header/>
    <soapenv:Body>
        <soap:sendSms>
            <username>?</username>
            <sms>
                <!--1 or more repetitions:-->
                <destinations>
                    <!--You may enter the following 2 items in any order-->
                    <phone></phone>
                    <id></id>
                </destinations>
                <message></message>
                <timing></timing>
                <source></source>
            </sms>
        </soap:sendSms>
    </soapenv:Body>
</soapenv:Envelope>
```

### `sendBulkSms`

Sends many different messages in one call. Different text to different destinations. If everyone gets the same text, `sendSms` is the right method instead.

```java
Response r = sendBulkSms("username", messages);
```

::: warning `timing` is ignored here
Setting `timing` on a message inside `sendBulkSms` has no effect. Schedule with `sendSms`, or use the [`bulk`](../endpoints/bulk.md) operation on the main endpoint, which does honour a batch-level `timing`.
:::

```xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:soap="https://my.textme.co.il/soap">
    <soapenv:Header/>
    <soapenv:Body>
        <soap:sendBulkSms>
            <username></username>
            <sms>
                <!--1 or more repetitions:-->
                <sms>
                    <!--1 or more repetitions:-->
                    <destinations>
                        <!--You may enter the following 2 items in any order-->
                        <phone></phone>
                        <id></id>
                    </destinations>
                    <message></message>
                    <timing></timing>
                    <source></source>
                </sms>
            </sms>
        </soap:sendBulkSms>
    </soapenv:Body>
</soapenv:Envelope>
```

### `getDlrReport`

Pulls delivery reports for ids you supplied when sending.

```java
DlrResponse dr = getDlrReport("username", dlrRequest);
```

::: warning Window limits differ from the main endpoint
Over SOAP the range may not exceed **30 days**, and the oldest reachable date is **one year** back. The [`dlr`](../endpoints/reports.md) operation on `/api` allows only **one week** per request, so a wide historical query is one of the few things SOAP does better.
:::

```xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:soap="https://my.textme.co.il/soap">
    <soapenv:Header/>
    <soapenv:Body>
        <soap:getDlrReport>
            <username></username>
            <dlrRequest>
                <!--1 or more repetitions:-->
                <id></id>
                <from></from>
                <to></to>
            </dlrRequest>
        </soap:getDlrReport>
    </soapenv:Body>
</soapenv:Envelope>
```

### `verify_phone`

Submits one or more numbers to become verified senders. Same operation as [`verify_phone`](../endpoints/verified-senders.md) on the main endpoint.

```java
Response r = verify_phone("username", phones);
```

```xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:soap="https://my.textme.co.il/soap">
    <soapenv:Header/>
    <soapenv:Body>
        <soap:verify_phone>
            <username>?</username>
            <phones>
                <!--1 or more repetitions:-->
                <phone>?</phone>
            </phones>
        </soap:verify_phone>
    </soapenv:Body>
</soapenv:Envelope>
```

## Client examples

### PHP

PHP's built-in `SoapClient` needs the token pushed in through a stream context, because it has no first-class header option.

```php
<?php
// The classes the WSDL maps onto.
class Phones {
    public $phone = [];
}

class Phone {
    public $id;
    public $phone;
    public $cl_id;
}

class Sms {
    public $destinations;
    public $message;
    public $timing;
    public $source;
    public $tag;
    public $add_unsubscribe;
}

class DlrRequest {
    public $id;
    public $from;
    public $to;
}
```

```php
<?php
// Connect, carrying the bearer token on every call.
$url = 'https://my.textme.co.il/soap?wsdl';
$accessToken = getenv('TEXTME_API_TOKEN');

$httpHeaders = [
    'http' => [
        'protocol_version' => 1.1,
        'header' => 'Authorization: Bearer '.$accessToken."\r\n",
    ],
];

$context = stream_context_create($httpHeaders);
$wsclient = new SoapClient($url, ['stream_context' => $context, 'encoding' => 'UTF-8']);
```

```php
<?php
// sendSms. The same text to two destinations.
$sms = new Sms();
$sms->source = 'Test';
$sms->message = 'sendSms test';

$phone = new Phone();
$phone->phone = ['055XXXXXXX', '052XXXXXXX'];
$phone->id = 'externalid1';

$sms->destinations = $phone;

$response = $wsclient->sendSms('username', '', $sms);
print_r($response);
```

```php
<?php
// sendBulkSms. A different message per destination.
$sms = new Sms();
$sms->source = 'Test';
$sms->message = 'sendBulkSms test';

$phone = new Phone();
$phone->phone = '052XXXXXXX';
$phone->id = 'externalid';
$sms->destinations = $phone;

$sms1 = new Sms();
$sms1->source = 'Test1';
$sms1->message = 'sendBulkSms test1';

$phone1 = new Phone();
$phone1->phone = '052XXXXXXX';
$phone1->id = 'externalid1';
$sms1->destinations = $phone1;

$response = $wsclient->sendBulkSms('username', '', [$sms, $sms1]);
print_r($response);
```

```php
<?php
// getDlrReport. Pull the reports for those external ids.
$dlr = new DlrRequest();
$dlr->id = ['externalid', 'externalid1'];
$dlr->from = '01/05/26 00:00';
$dlr->to = '07/05/26 18:29';

$response = $wsclient->getDlrReport('username', '', $dlr);
print_r($response);
```

### Java

Built on `javax.xml.soap`, assembling the envelope by hand and attaching the token as a MIME header.

```java
import javax.xml.soap.*;
import java.util.ArrayList;

public class TextMeSoapBulk {
    private static SOAPElement smsContainer;

    public static void main(String[] args) {
        String endpoint = "https://my.textme.co.il/soap?wsdl";
        String soapAction = "https://my.textme.co.il/soap/";
        String token = System.getenv("TEXTME_API_TOKEN");
        String username = "";  // your account username
        String source = "";    // a verified sender
        String message = "";   // the text to send

        ArrayList<String> destinations = new ArrayList<>();
        destinations.add("55999xxxx");

        call(endpoint, soapAction, username, token, message, source, destinations);
    }

    private static void createEnvelope(SOAPMessage soapMessage, String username)
            throws SOAPException {
        SOAPEnvelope envelope = soapMessage.getSOAPPart().getEnvelope();
        envelope.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema");

        SOAPElement body = envelope.getBody().addChildElement("sendBulkSms");
        body.addChildElement("username").addTextNode(username);
        smsContainer = body.addChildElement("sms");
    }

    private static void addDestination(String phone, String message, String source) {
        try {
            SOAPElement sms = smsContainer.addChildElement("sms");
            SOAPElement destinations = sms.addChildElement("destinations");
            destinations.addChildElement("phone").addTextNode(phone);
            sms.addChildElement("message").addTextNode(message);
            sms.addChildElement("source").addTextNode(source);
        } catch (SOAPException e) {
            e.printStackTrace();
        }
    }

    private static void call(String endpoint, String soapAction, String username,
            String token, String message, String source, ArrayList<String> destinations) {
        try (SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection()) {
            SOAPMessage request = MessageFactory.newInstance().createMessage();
            createEnvelope(request, username);

            for (String destination : destinations) {
                addDestination(destination, message, source);
            }

            MimeHeaders headers = request.getMimeHeaders();
            headers.addHeader("SOAPAction", soapAction);
            headers.addHeader("Authorization", "Bearer " + token);
            request.saveChanges();

            SOAPMessage response = connection.call(request, endpoint);
            response.writeTo(System.out);
        } catch (Exception e) {
            System.err.println("SOAP request failed. Check the endpoint URL and SOAPAction.");
            e.printStackTrace();
        }
    }
}
```

::: tip Prefer the main endpoint from Java
Assembling SOAP envelopes by hand is a lot of ceremony for one message. The same send over the [`/api` endpoint](../endpoints/send.md) is a dozen lines of `java.net.http`. The Java tab on any endpoint page shows it.
:::
