PHPackages                             orynlabs/smsgo - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Mail &amp; Notifications](/categories/mail)
4. /
5. orynlabs/smsgo

ActiveLibrary[Mail &amp; Notifications](/categories/mail)

orynlabs/smsgo
==============

SDK oficial da SMSGo para PHP — envio de SMS (OTP/2FA, alertas, campanhas), consulta de envios, saldo, faturamento off-session, recarga automática e webhooks de saída.

v0.3.0(today)00MITPHPPHP &gt;=8.1CI passing

Since Jul 1Pushed todayCompare

[ Source](https://github.com/sms-go/smsgo-sdk-php)[ Packagist](https://packagist.org/packages/orynlabs/smsgo)[ Docs](https://smsgo.com.br)[ RSS](/packages/orynlabs-smsgo/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (3)Versions (3)Used By (0)

orynlabs/smsgo
==============

[](#orynlabssmsgo)

[![Packagist](https://camo.githubusercontent.com/7a1352e6b912c4578ef31297f7431f5138351f8579041e8b93e6cf24bd7aa112/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6f72796e6c6162732f736d73676f2e737667)](https://packagist.org/packages/orynlabs/smsgo)[![PHP](https://camo.githubusercontent.com/83b05acc7e69aff3f6b29117d97e15effb4d6a99ef0cac83101431ef3e6b6cb5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6f72796e6c6162732f736d73676f2e737667)](https://packagist.org/packages/orynlabs/smsgo)[![license](https://camo.githubusercontent.com/d2adba28c60983f4e5a2d1715a637d35de3b5d0446d60f67a2b84dd3ef725157/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6f72796e6c6162732f736d73676f2e737667)](./LICENSE)

SDK oficial **PHP** para a [SMSGo](https://smsgo.com.br) — a API de SMS simples para o Brasil. Envie **OTP/2FA, alertas transacionais e campanhas** com poucas linhas de código.

- ⚡ **Integra em minutos** — autenticação cuidada pra você (sem ritual de token manual).
- 💸 **Sem mensalidade** — créditos pré-pagos que não expiram, preço em real.
- 🇧🇷 **Brasil-first** — entrega para todas as operadoras, LGPD nativo.
- 🟢 **Zero dependências** — só `ext-json` + `ext-curl`. Tipado com DTOs `readonly`.
- 🎁 **R$ 10 grátis** ao criar a conta — dá pra testar sem cartão.

> Nova conta e chave em **[smsgo.com.br](https://smsgo.com.br)** → painel → **Minha conta → API**.

Requisitos
----------

[](#requisitos)

- PHP **8.1+**
- Extensões `ext-json` e `ext-curl`

Instalação
----------

[](#instalação)

```
composer require orynlabs/smsgo
```

Começo rápido
-------------

[](#começo-rápido)

```
use Orynlabs\SMSGo\Client;

$client = new Client(getenv('SMSGO_KEY'));

$result = $client->send(
    phone: '+5511999990000',
    message: 'Olá do SMSGo',
);

echo $result->id . ' ' . $result->status; // -> "a1b2c3...", "queued"
```

Você passa só a `apiKey`. O SDK troca a chave por um token Bearer (válido 48h), guarda em cache e renova sozinho quando expira (ou no primeiro `401`).

O construtor aceita opções:

```
$client = new Client(getenv('SMSGO_KEY'), [
    'baseUrl'   => 'https://api.smsgo.com.br', // default; só mexa se a SMSGo orientar
    'timeout'   => 30,                          // segundos
    // 'transport' => $meuTransport,            // injeta um Http\Transport (testes)
]);
```

Enviar um OTP (2FA)
-------------------

[](#enviar-um-otp-2fa)

```
$code = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);

$client->send(
    phone: $user->phone,
    message: "Seu código SMSGo é {$code}. Válido por 5 minutos.",
);
// guarde $code (com TTL) e compare na verificação
```

Envio em massa
--------------

[](#envio-em-massa)

```
$client->sendBulk(
    messages: [
        ['phone' => '+5511999990000', 'message' => 'Oi, Ana!'],
        ['phone' => '+5521988887777', 'message' => 'Oi, Bruno!'],
    ],
    urlCallback: 'https://seuapp.com/webhooks/smsgo', // status de entrega (opcional)
);
```

Consultar envios
----------------

[](#consultar-envios)

```
$page = $client->list(page: 1);         // Paginated — { meta, data }
$one  = $client->get('a1b2c3-...');     // SendDetail + summary { total, delivered, failed, inProgress, done }

// Acompanhar um envio grande sem baixar tudo — números por bucket, paginado:
$failed = $client->getNumbers('a1b2c3-...', status: 'failed', page: 1);
```

Modo de teste (sandbox)
-----------------------

[](#modo-de-teste-sandbox)

Use a **chave de teste** (prefixo `test_`, no painel → Minha conta → API) como `apiKey`. Nada muda no código: os envios **não debitam saldo nem são despachados de verdade**, as respostas são idênticas às de produção (com `test: true`) e os webhooks disparam com o mesmo flag.

```
$sandbox = new Client(getenv('SMSGO_TEST_KEY'));
$r = $sandbox->send(phone: '+5511999990000', message: 'Teste');
$r->test; // true

$sandbox->resolveMode(); // "test"  (ou $sandbox->mode() após a 1ª chamada)
```

Saldo e catálogo
----------------

[](#saldo-e-catálogo)

```
$balance = $client->getBalance();  // Balance { balance, currency, company }
echo $balance->balance;            // 9.3

$types = $client->getSmsTypes();   // list { id, name, price, sale } — id vai em smsTypeId
```

Comprar créditos (off-session)
------------------------------

[](#comprar-créditos-off-session)

Cobra um **cartão salvo** sem abrir o painel (o cartão é cadastrado no painel via Stripe; a API só cobra um já salvo).

```
$plans = $client->billing->plans(); // list — pacotes por faixa
$cards = $client->billing->cards(); // list — 4 últimos dígitos

$receipt = $client->billing->purchase(quantity: 5000 /*, planId:, cardId:, coupon: */);
$receipt->status; // 'succeeded' já creditou o saldo | 'processing' confirma via webhook

$invoices = $client->billing->invoices(page: 1);
```

> **Idempotência:** cada `purchase` gera uma cobrança nova. Em timeout, consulte `billing->invoices()` antes de repetir — **não faça retry cego**. O endpoint tem rate-limit estrito (6/min).

Recarga automática + alerta de saldo
------------------------------------

[](#recarga-automática--alerta-de-saldo)

```
$client->setAutoRecharge(
    enabled: true,
    threshold: 5,        // recarrega quando o saldo ≤ R$ 5
    planQuantity: 5000,  // créditos por recarga
    cardId: '',    // obrigatório p/ ligar
    alertEnabled: true,
    alertThreshold: 15,  // e-mail quando o saldo ≤ R$ 15
);

$cfg = $client->getAutoRecharge();
```

Webhooks de saída (DLR + respostas)
-----------------------------------

[](#webhooks-de-saída-dlr--respostas)

```
// Define a URL que recebe `sms.status` (DLR) e `sms.reply` (resposta). Guarde o secret.
$cfg = $client->setWebhook(url: 'https://seuapp.com/webhooks/smsgo');
$cfg->url; $cfg->secret;

$client->setWebhook(rotateSecret: true); // gira o segredo
$client->setWebhook(url: '');            // desativa
```

Cada requisição traz `X-SMSGo-Signature: sha256=` — o HMAC-SHA256 do **corpo bruto** com o seu `secret`. **Valide sempre** com o helper `Webhook::verifySignature()` (comparação em tempo constante):

```
use Orynlabs\SMSGo\Webhook;

$rawBody   = file_get_contents('php://input');           // bytes exatos — não re-serialize!
$signature = $_SERVER['HTTP_X_SMSGO_SIGNATURE'] ?? null;

if (! Webhook::verifySignature($rawBody, $signature, $secret)) {
    http_response_code(401);
    exit;
}
```

Veja [`examples/receive-dlr-webhook.php`](./examples/receive-dlr-webhook.php) para o handler completo.

Contatos e listas
-----------------

[](#contatos-e-listas)

```
$listId = $client->lists->create(name: 'Clientes VIP')->id;

$contactId = $client->contacts->create(
    fullName: 'Ana Souza',
    phone: '+5511999990000',
    email: 'ana@exemplo.com',
    lists: [$listId],
);

$client->contacts->list(page: 1, search: 'ana'); // Paginated { meta, data }
$client->contacts->update($contactId, fullName: 'Ana S.', phone: '+5511999990000');
$client->contacts->delete($contactId);
```

Tratamento de erros
-------------------

[](#tratamento-de-erros)

Toda resposta não-2xx vira um `SMSGoError` com `status` e um `code` estável:

```
use Orynlabs\SMSGo\Client;
use Orynlabs\SMSGo\SMSGoError;

try {
    $client->send(phone: '+5511999990000', message: 'Olá');
} catch (SMSGoError $e) {
    switch ($e->code) {
        case 'insufficient_balance': // 402 — sem saldo
        case 'rate_limited':         // 429 — muitas requisições (veja $e->details)
        case 'validation_error':     // 422 — dados inválidos ($e->errors por campo)
        default:
            error_log("{$e->status} {$e->code} {$e->getMessage()}");
    }
}
```

Em falhas de validação (422), `$e->errors` traz o detalhe por campo (`list`). Falhas de rede/transporte viram `SMSGoError` com `status = 0` e `code = 'network_error'`.

`code`HTTPSignificado`validation_error`422Dados do request inválidos`unauthorized`401Chave/token inválido`insufficient_balance`402Saldo insuficiente`provider_out_of_stock`409Estoque do provedor indisponível`rate_limited`429Limite de requisições atingido`card_declined`402Cartão recusado na compra`authentication_required`402Cartão exige autenticação (SCA)`card_required`400Nenhum cartão apto à cobrança`payment_unavailable`503Gateway de pagamento indisponível`network_error`0Falha de rede/transporte (cliente)Referência da API
-----------------

[](#referência-da-api)

### `new Client(string $apiKey, array $options = [])`

[](#new-clientstring-apikey-array-options--)

OpçãoTipoDefaultDescrição`apiKey``string`—**Obrigatório.** Sua SMSGo-key (aceita `test_…`).`baseUrl``string``https://api.smsgo.com.br`Não precisa mexer; só se a SMSGo orientar.`timeout``int``30`Timeout total, em segundos.`transport``Http\Transport``Http\CurlTransport`Injete um transporte (ex.: testes).### Métodos

[](#métodos)

**SMS**

- `send(phone, message, schedule?, reference?, from?, smsTypeId?)` → `SendResult`
- `sendBulk(messages, urlCallback?, flashSms?, smsTypeId?)` → `SendResult`
- `list(page = 1)` → `Paginated`
- `get(id)` → `SendDetail` (com `summary`)
- `getNumbers(id, status?, page?)` → `Paginated` (`status`: `delivered` · `failed` · `in_progress`)
- `getSmsTypes()` → `list`

**Conta**

- `getBalance()` → `Balance`
- `getAutoRecharge()` / `setAutoRecharge(...)` → `AutoRechargeConfig`
- `getWebhook()` / `setWebhook(url?, rotateSecret?)` → `WebhookConfig`
- `mode()` → `'live' | 'test' | null` · `resolveMode()` → `'live' | 'test'`

**Faturamento** (`$client->billing`)

- `plans()` → `list` · `cards()` → `list` · `invoices(page?, perPage?)` → `Paginated`
- `purchase(quantity?, planId?, cardId?, coupon?)` → `PurchaseResult`

**Contatos** (`$client->contacts`)

- `list(page, perPage?, search?, title?)` · `create(fullName, phone, email?, lists?)` → `string` (uuid)
- `get(id)` → `ContactDetail` · `update(id, fullName, phone, email?, lists?)` → `string` · `delete(id)` → `array{message}`

**Listas** (`$client->lists`)

- `list(page, perPage?, title?)` · `create(name)` → `ListResult` · `get(id)` → `ListResult`
- `update(id, name)` → `ListResult` · `delete(id)` → `array{message}`

**Webhook** (estático)

- `Webhook::verifySignature(rawBody, signatureHeader, secret)` → `bool`

> Referência de máquina completa: **[smsgo.apidog.io](https://smsgo.apidog.io/)** — importável no Apidog/Postman.

Exemplos
--------

[](#exemplos)

Na pasta [`examples/`](./examples):

```
composer install
SMSGO_KEY=suachave php examples/otp.php +5511999990000
```

- [`send.php`](./examples/send.php) — envio simples
- [`otp.php`](./examples/otp.php) — código OTP/2FA
- [`status.php`](./examples/status.php) — envio em massa + consulta de status
- [`balance.php`](./examples/balance.php) — saldo + catálogo de tipos de SMS
- [`buy-credits.php`](./examples/buy-credits.php) — compra off-session + recarga automática
- [`configure-webhook.php`](./examples/configure-webhook.php) — configura o webhook de saída
- [`receive-dlr-webhook.php`](./examples/receive-dlr-webhook.php) — recebe callbacks de entrega (DLR) e valida a assinatura

Desenvolvimento
---------------

[](#desenvolvimento)

```
composer install
composer test      # PHPUnit
composer phpstan   # análise estática (nível 8)
composer cs-check  # PHP-CS-Fixer (dry-run)
```

Migrando da TotalVoice / Twilio?
--------------------------------

[](#migrando-da-totalvoice--twilio)

SMSGo foca em **DX simples e preço em real**. Sem cadastro de remetente pra começar, sem cobrança em dólar, créditos que não expiram. Documentação completa da API: **[smsgo.apidog.io](https://smsgo.apidog.io/)**.

Licença
-------

[](#licença)

MIT © SMSGo

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity33

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/789e7ab9b62e126b925fe814e402424d3c603c1a5f08c013757905e434863558?d=identicon)[Gabrielmoraesp](/maintainers/Gabrielmoraesp)

---

Top Contributors

[![Gabrielmoraesp](https://avatars.githubusercontent.com/u/440323?v=4)](https://github.com/Gabrielmoraesp "Gabrielmoraesp (7 commits)")

---

Tags

sdkotp2fasmswebhookbrasilsmsgo

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/orynlabs-smsgo/health.svg)

```
[![Health](https://phpackages.com/badges/orynlabs-smsgo/health.svg)](https://phpackages.com/packages/orynlabs-smsgo)
```

###  Alternatives

[ferdous/laravel-otp-validate

Laravel package for OTP validation with built-in features like retry and resend mechanism. Built in max retry and max resend blocking. OTP/Security Code can be send over SMS or Email of your choice with user-defined template.

7024.6k](/packages/ferdous-laravel-otp-validate)[jjonline/aliyun-dysms-php-sdk

Aliyun SMS SDK for PHP

21100.2k](/packages/jjonline-aliyun-dysms-php-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
