Before you start
- An API connection created in the web panel (app.grupotecnophone.com), with its Bearer Token for sandbox or production.
- Your server’s public IP registered as authorized for that token.
- A User-Agent header that identifies your application, for example
MyCompany/1.0. - Java 11 or later (includes
java.net.http.HttpClient).
Store the token in an environment variable (in these examples, GTP_SMS_TOKEN) and never include it in the code of a mobile app or website: API calls must always come from your backend, from an authorized IP.
Send an SMS with Java
The following example sends an SMS with Java’s standard HTTP client. In production, parse the JSON response with the library your project already uses:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class EnviarSms {
private static final String ENDPOINT = "https://api.grupotecnophone.com/prod/v1/sms/send";
public static void main(String[] args) throws Exception {
String token = System.getenv("GTP_SMS_TOKEN");
String json = "{\"to\":\"+525512345678\","
+ "\"body\":\"Your verification code is 482913. It expires in 5 minutes.\"}";
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
HttpRequest request = HttpRequest.newBuilder(URI.create(ENDPOINT))
.timeout(Duration.ofSeconds(30))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.header("User-Agent", "MyCompany/1.0")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("HTTP " + response.statusCode());
System.out.println(response.body()); // parse the JSON with your usual library (Jackson, Gson)
}
}
API response
If the message was accepted, the API responds with HTTP 200 and a JSON body like this:
{
"sid": "sms_20261012143201_39bdafbd",
"status": "success",
"to": "+525512345678",
"body": "Your verification code is 482913. It expires in 5 minutes.",
"encoding": "GSM7",
"num_chars": 56,
"num_segments": 1,
"error": null
}
Store the sid: it is the identifier you will use to reconcile the message’s delivery report. The num_segments field indicates how many segments will be billed; see how segments are calculated.
Send SMS to multiple recipients with Java
To send bulk SMS from Java, reuse a single HttpClient and loop through your list of numbers. In production, read the response with a JSON library (Jackson or Gson) to store the sid and keep errors separate.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.List;
public class EnvioMasivo {
private static final String ENDPOINT = "https://api.grupotecnophone.com/prod/v1/sms/send";
private static final String TOKEN = System.getenv("GTP_SMS_TOKEN");
private static final HttpClient CLIENT = HttpClient.newHttpClient();
static HttpResponse<String> sendSms(String to, String body) throws Exception {
String json = "{\"to\":\"" + to + "\",\"body\":\"" + body.replace("\"", "\\\"") + "\"}";
HttpRequest req = HttpRequest.newBuilder(URI.create(ENDPOINT))
.timeout(Duration.ofSeconds(30))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.header("User-Agent", "MiEmpresa/1.0")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
return CLIENT.send(req, HttpResponse.BodyHandlers.ofString());
}
public static void main(String[] args) throws Exception {
List<String> recipients = List.of("+525512345678", "+525598765432");
for (String number : recipients) {
HttpResponse<String> resp = sendSms(number, "Your order 1234 is on its way.");
System.out.println(number + " -> " + resp.statusCode() + " " + resp.body());
Thread.sleep(100); // moderate pace for large lists
}
}
}
For very large lists, process in batches and retry only temporary errors. Without coding, you can also send bulk SMS from Excel or CSV.
Send an OTP code with Java
For verification codes use SecureRandom, never Random, and store only the hash of the code with its expiry.
import java.security.SecureRandom;
SecureRandom random = new SecureRandom();
String otp = String.format("%06d", random.nextInt(1_000_000));
sendSms("+525512345678", "Your verification code is " + otp + ". It expires in 5 minutes.");
// Store only the code hash and its expiry date
More details on the flow in the guide to SMS OTP authentication.
Common errors
| HTTP | Code | Meaning |
|---|---|---|
| 400 | ENCRYPTION_REQUIRED | The connection requires to and body to be encrypted with RSA-OAEP |
| 400 | ENCRYPTION_NOT_ALLOWED | The connection operates in plain text and encrypted content was received |
| 400 | INPUT_PHONE_BLACKLISTED | The destination number is on the blacklist |
| 400 | INSUFFICIENT_BALANCE | Insufficient balance for the send |
| 401 | — | Missing or invalid token |
| 403 | — | The source IP is not authorized for the token |
| 500 | — | Unexpected internal error |
On 400 errors the response includes an error object with code, code_num and message.
Test in sandbox
Change the endpoint to https://api.grupotecnophone.com/test/v1/sms/send and use the sandbox token. That environment validates the token, IP, payload and encryption with the same logic as production, but does not send real SMS.
Best practices
- Set a timeout and log each response with its
sid. - After a network error with no response, do not resend blindly: check first so you don’t duplicate the message to the user.
- Retry only 500 errors, with progressive backoff and a maximum number of attempts.
- Queue bulk sends instead of sending them within a web request cycle.
- If the content is sensitive, enable connection encryption; the API documentation includes an RSA encryption example in PHP without external libraries.
See also the SMS API for Mexico, the SMPP connection and the guides for PHP, Laravel, Python and Node.js. If you need test credentials, contact us.


