Antes de empezar
- Una conexión API creada en el panel web (app.grupotecnophone.com), con su Bearer Token de sandbox o de producción.
- La IP pública de su servidor registrada como autorizada para ese token.
- Un User-Agent que identifique a su aplicación, por ejemplo
MiEmpresa/1.0. - Laravel 9 o superior (el cliente
Httpviene incluido) y un sistema de colas configurado si enviará en segundo plano.
Guarde el token en una variable de entorno (en estos ejemplos, GTP_SMS_TOKEN) y nunca lo incluya en el código de una app móvil o de un sitio web: las llamadas a la API deben salir siempre de su backend, desde una IP autorizada.
Enviar un SMS con Laravel
1. Configuración. Agregue las credenciales a config/services.php y defina GTP_SMS_TOKEN en su archivo .env:
// config/services.php
'gtp_sms' => [
'token' => env('GTP_SMS_TOKEN'),
'endpoint' => env('GTP_SMS_ENDPOINT', 'https://api.grupotecnophone.com/prod/v1/sms/send'),
],
2. Servicio. Centralice el envío en una clase reutilizable:
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use RuntimeException;
class SmsService
{
public function send(string $to, string $body): array
{
$response = Http::withToken(config('services.gtp_sms.token'))
->withHeaders(['User-Agent' => 'MiEmpresa/1.0'])
->acceptJson()
->timeout(30)
->post(config('services.gtp_sms.endpoint'), [
'to' => $to,
'body' => $body,
]);
$data = $response->json() ?? [];
if ($response->successful() && ($data['status'] ?? null) === 'success') {
return $data; // sid, encoding, num_chars, num_segments
}
$code = $data['error']['code'] ?? 'HTTP_' . $response->status();
throw new RuntimeException($code . ': ' . ($data['error']['message'] ?? $response->body()));
}
}
3. Envío en cola. Para no bloquear la petición web —y para absorber picos de envío— despache un job:
<?php
namespace App\Jobs;
use App\Services\SmsService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class SendSms implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 1; // evita reenvios duplicados ante errores de red
public function __construct(public string $to, public string $body)
{
}
public function handle(SmsService $sms): void
{
$result = $sms->send($this->to, $this->body);
Log::info('SMS aceptado', ['sid' => $result['sid'], 'segmentos' => $result['num_segments']]);
}
}
// Desde un controlador o un listener:
// SendSms::dispatch('+525512345678', 'Su codigo de verificacion es 482913. Vence en 5 minutos.');
Respuesta de la API
Si el mensaje fue aceptado, la API responde con HTTP 200 y un JSON como este:
{
"sid": "sms_20261012143201_39bdafbd",
"status": "success",
"to": "+525512345678",
"body": "Su codigo de verificacion es 482913. Vence en 5 minutos.",
"encoding": "GSM7",
"num_chars": 56,
"num_segments": 1,
"error": null
}
Guarde el sid: es el identificador con el que podrá conciliar el reporte de entrega del mensaje. El campo num_segments indica cuántos segmentos se cobrarán; vea cómo se calculan los segmentos.
Errores frecuentes
| HTTP | Código | Qué significa |
|---|---|---|
| 400 | ENCRYPTION_REQUIRED | La conexión exige que to y body viajen cifrados con RSA-OAEP |
| 400 | ENCRYPTION_NOT_ALLOWED | La conexión opera en texto plano y se recibió contenido cifrado |
| 400 | INPUT_PHONE_BLACKLISTED | El número de destino está en lista negra |
| 400 | INSUFFICIENT_BALANCE | Saldo insuficiente para el envío |
| 401 | — | Token ausente o inválido |
| 403 | — | La IP de origen no está autorizada para el token |
| 500 | — | Error interno no esperado |
En los errores 400 la respuesta incluye un objeto error con code, code_num y message.
Probar en sandbox
Cambie el endpoint por https://api.grupotecnophone.com/test/v1/sms/send y use el token de sandbox. Ese entorno valida token, IP, payload y cifrado con la misma lógica que producción, pero no envía SMS reales.
Buenas prácticas
- Defina un timeout y registre cada respuesta con su
sid. - Ante un error de red sin respuesta, no reenvíe a ciegas: verifique primero para no duplicar el mensaje al usuario.
- Reintente solo errores 500, con espera progresiva y un número máximo de intentos.
- Encole los envíos masivos en lugar de enviarlos en el ciclo de una petición web.
- Si el contenido es sensible, active el cifrado de la conexión; la documentación de la API incluye un ejemplo de cifrado RSA en PHP sin librerías externas.
Vea también la API SMS México, la conexión SMPP y las guías para PHP, Python, Node.js y Java. Si necesita credenciales de prueba, contáctenos.


