Nothing found

Backup server

The backup server is a second address running the very same API. It is there for the case when a request to portal.bulkgate.com does not reach its destination at all — the backup host accepts the request and forwards it over a different route.

How the service is built

BulkGate runs on several servers in three geographical locations. If one of them goes down, the remaining ones take the traffic over automatically — nothing changes for your integration and portal.bulkgate.com keeps answering. That case needs no handling on your side. The whole setup is described in Infrastructure.

What this does not cover is the route to us. An outage on the path between your server and ours — at a carrier, at a connectivity provider or anywhere in between — is outside our control, and the request then never reaches us at all. That is what the backup host is for.

The current service status is at bulkgate.status.online.

Address

https://backup1.bulkgate.com

The host is a one-to-one replacement — paths, parameters, credentials and responses are identical to portal.bulkgate.com. All you swap is the domain:

https://portal.bulkgate.com/api/2.0/advanced/transactional https://backup1.bulkgate.com/api/2.0/advanced/transactional

It works with the same account, the same token and the same credit. There is nothing to set up and nothing to switch on.

Caution

Do not use the backup host as your primary address. It can be taken down for maintenance at any time and without notice — it is meant to carry traffic only while the main host is unreachable. Keep portal.bulkgate.com first in the order.

When to switch to it

Important

The backup host solves a connection failure, not a rejected request. To a request the API refused it replies exactly the same way.

Switch when the request gets no answer:

situation switch?
Connection or read timeout Yes
DNS could not be resolved Yes
Connection refused, network unreachable Yes
HTTP 5xx with no body Yes
A response with an error type (4xx) No
429 Too Many Requests (limits No

In the last two cases the API did answer — the request arrived and was evaluated. Repeating it on the backup host returns the same error and only burns another attempt from your limit.

Building the failover into your integration

Keep the addresses in an ordered list and try them one after another. If the connection fails, move on to the next one; if the API answered, return the result as it is.

$hosts = ['portal.bulkgate.com', 'backup1.bulkgate.com']; foreach ($hosts as $host) { $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => "https://$host/api/2.0/advanced/transactional", CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode([ 'application_id' => 451, 'application_token' => 'NKN02TWE6NfBkfl-your-secret-token-Wf05GaqLIWLW4aBj', 'number' => ['447820125799'], 'text' => 'Your order 4517 has been shipped.', // Guard against sending twice when the first attempt timed out // but the message went through anyway — see What to watch out for. 'duplicates_check' => 'on', ], JSON_THROW_ON_ERROR), ]); $body = curl_exec($curl); $error = curl_error($curl); curl_close($curl); // The connection failed — try the next address. if ($body === false) { continue; } // The API answered, whether with a success or an error. No more switching. print_r(json_decode($body, true, flags: JSON_THROW_ON_ERROR)); break; } # pip install requests import requests hosts = ['portal.bulkgate.com', 'backup1.bulkgate.com'] for host in hosts: try: response = requests.post(f'https://{host}/api/2.0/advanced/transactional', json={ 'application_id': 451, 'application_token': 'NKN02TWE6NfBkfl-your-secret-token-Wf05GaqLIWLW4aBj', 'number': ['447820125799'], 'text': 'Your order 4517 has been shipped.', 'duplicates_check': 'on', }, timeout=30) except requests.RequestException: continue # the connection failed, try the next address print(response.json()) break const hosts = ['portal.bulkgate.com', 'backup1.bulkgate.com']; for (const host of hosts) { let response; try { response = await fetch(`https://${host}/api/2.0/advanced/transactional`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ application_id: 451, application_token: 'NKN02TWE6NfBkfl-your-secret-token-Wf05GaqLIWLW4aBj', number: ['447820125799'], text: 'Your order 4517 has been shipped.', duplicates_check: 'on', }), }); } catch { continue; // the connection failed, try the next address } console.log(await response.json()); break; }

What to watch out for

Warning

A timeout does not mean the message was not sent. The request may have arrived and the response got lost on the way back — a retry on the backup host would then send the message a second time.

That is why you should send duplicates_check enabled on the transactional endpoints. A message with the same text to the same number is dropped within a 5 minute window, so the repeated attempt duplicates nothing.

Important

On promotional endpoints duplicates_check does not protect a retry — it only removes duplicates within a single batch, not across requests. A repeated request is a new batch to it and goes out in full. For bulk sends, rather check whether the first attempt went through before repeating it.

Set a sensible timeout. Without one the client waits for an answer that never comes and never reaches the backup host at all.

Note

API idempotency is in development — a repeated request will be markable so that the API recognises it and returns the result of the original one instead of sending again. That will remove the difference between transactional and promotional endpoints described above. We will document the procedure here as soon as it is available.

Was this page helpful?