convertaja / sdk
SDK oficial da API do Convertajá: PDF, DANFE, etiquetas ZPL, assinatura eletrônica, CNPJ, CEP, boleto e Pix.
Requires
- php: >=8.1
- ext-curl: *
- ext-json: *
Requires (Dev)
- phpunit/phpunit: ^10.5 || ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is not auto-updated.
Last update: 2026-11-02 02:30:11 UTC
README
SDK oficial da API do Convertajá para PHP: comprimir e converter PDF, gerar DANFE a partir do XML da NF-e, converter etiquetas ZPL, assinatura eletrônica, Central de Expedição e consultas de CNPJ, CEP, boleto e Pix.
- PHP 8.1 ou mais novo, só
ext-curleext-json(sem Guzzle). - PSR-4 (
Convertaja\). - Repete sozinho em falha de rede, 429 (respeitando
Retry-After) e 5xx, sem cobrar duas vezes (Idempotency-Key automática).
Ainda não publicado no Packagist. Até a publicação, instale pelo caminho local ou pelo repositório git (veja abaixo).
Instalação
composer require convertaja/sdk
Primeiros passos
Crie a chave em Minha conta → API (/conta/api). Use cj_test_… para testar (não consome créditos, até 20 chamadas por dia) e cj_live_… em produção.
<?php require 'vendor/autoload.php'; use Convertaja\Client; $cj = new Client(getenv('CONVERTAJA_API_KEY')); // opções: new Client('cj_live_...', ['base_url' => ..., 'max_retries' => 2, 'timeout' => 120, 'retry_delay' => 0.5]) $me = $cj->me(); echo $me['plan']['label'], ' ', $me['credits']['remaining'], PHP_EOL; echo 'Créditos depois da última chamada: ', $cj->creditsRemaining(), PHP_EOL;
Comprimir um PDF
// 'wait' => true segura a resposta até 60 s; se ainda não terminou, use jobs->wait $job = $cj->tools->run('comprimir-pdf', [ 'files' => ['contrato.pdf'], // caminho, ['data' => $bytes, 'name' => …], ['url' => …] ou ['base64' => …, 'name' => …] 'options' => ['level' => 'high'], // low | medium | high 'wait' => true, ]); if (!in_array($job['status'], ['done', 'error'], true)) { $job = $cj->jobs->wait($job['id']); } if ($job['status'] === 'error') { throw new RuntimeException($job['error']['message']); } $arquivo = $cj->jobs->download($job['id']); // um arquivo, ou ZIP se houver vários $arquivo->save($arquivo->filename ?? 'comprimido.pdf');
Consultar CNPJ e CEP (grátis)
$empresa = $cj->lookups->cnpj('11.222.333/0001-81'); // aceita o CNPJ alfanumérico echo $empresa['razaoSocial'], ' - ', $empresa['situacao'], PHP_EOL; $endereco = $cj->lookups->cep('01310-100'); echo $endereco['logradouro'], ', ', $endereco['cidade'], '/', $endereco['uf'], PHP_EOL;
DANFE a partir do XML da NF-e
$job = $cj->tools->run('xml-nfe-para-pdf', [ 'files' => ['nota.xml'], // vários XMLs ou um ZIP 'options' => ['layout' => 'a4'], // a4 | simplificado (10×15, etiqueta) 'wait' => true, ]); $cj->jobs->download($job['id'])->save('danfe.pdf');
ZPL para PDF
// código ZPL direto nas opções (sem arquivo)... $job = $cj->tools->run('zpl-para-pdf', [ 'options' => ['zpl' => '^XA^FO50,50^A0N,40,40^FDOlá^FS^XZ', 'width_mm' => 100, 'height_mm' => 150, 'dpmm' => '8'], 'wait' => true, ]); // ...ou arquivos .zpl/.txt $job = $cj->tools->run('zpl-para-pdf', ['files' => ['etiquetas.zpl'], 'wait' => true]); $cj->jobs->download($job['id'])->save('etiquetas.pdf');
Liste as ferramentas, extensões aceitas e opções (JSON Schema) com $cj->tools->list() ou $cj->tools->get('comprimir-pdf').
Assinatura eletrônica (envelope)
$envelope = $cj->esign->envelopes->create([ 'file' => 'contrato.pdf', // ou ['url' => 'https://…/contrato.pdf'] 'name' => 'Contrato de prestação de serviços', 'message' => 'Olá! Segue o contrato para assinatura.', 'signers' => [ ['name' => 'Ana Souza', 'email' => 'ana@cliente.com.br', 'role' => 'sign'], ['name' => 'Bruno Lima', 'email' => 'bruno@empresa.com.br', 'role' => 'witness'], ], 'fields' => [ ['signer' => 0, 'type' => 'signature', 'page' => 0, 'x' => 0.1, 'y' => 0.75, 'w' => 0.3, 'h' => 0.07], ['signer' => 1, 'type' => 'signature', 'page' => 0, 'x' => 0.55, 'y' => 0.75, 'w' => 0.3, 'h' => 0.07], ], 'webhook_url' => 'https://seusite.com.br/webhooks/convertaja', ]); echo $envelope['id'], ' ', $envelope['status'], PHP_EOL; // K7QD-9WZ2-M4HT-R8PA pending // depois que todos assinarem: $cj->esign->envelopes->downloadFinal($envelope['id'])->save('contrato-assinado.pdf');
Também há list, listAll, get($id, ['events' => true, 'links' => true]), send (rascunhos criados com 'send' => false), remind, cancel, delete e downloadAudit.
Outros recursos
$cj->validate(['type' => 'cnpj', 'value' => '12.ABC.345/01DE-35']); $cj->validate(['values' => ['123.456.789-09', '11.222.333/0001-81']]); // lote: 1 crédito a cada 50 $cj->boleto->parse('23793.38128 86000.782713 36950.000632 1 10000000012345'); $cj->pix->brcode(['key' => 'contato@empresa.com.br', 'name' => 'Empresa', 'city' => 'SAO PAULO', 'amount' => 10.5, 'format' => 'png']); $cj->qrcode(['text' => 'https://convertaja.com.br', 'format' => 'svg']); $cj->barcode(['type' => 'ean13', 'value' => '789123456789', 'format' => 'png']); // Tarefas $page = $cj->jobs->list(['status' => 'done', 'limit' => 20]); // $page['next_cursor'] → starting_after foreach ($cj->jobs->listAll(['tool' => 'comprimir-pdf']) as $job) { echo $job['id'], PHP_EOL; } $cj->jobs->downloadFile($jobId, 0)->save('saida.pdf'); $cj->jobs->delete($jobId); // apaga os arquivos antes de 1 hora (LGPD) // Central de Expedição: etiquetas + XMLs das notas $lote = $cj->expedicao->lotes->create(['labels' => ['etiquetas.pdf'], 'xmls' => ['notas.zip'], 'intercalar' => true, 'wait' => true]); $lote = $cj->expedicao->lotes->wait($lote['id']); $cj->expedicao->lotes->download($lote['id'])->save('expedicao.zip'); // Webhook de teste (envia um evento assinado para a sua URL) $cj->webhooks->test('https://seusite.com.br/webhooks/convertaja');
Webhooks: verificação da assinatura
Cada aviso chega com X-Convertaja-Signature: t=<unix>,v1=<hex>, onde v1 = HMAC-SHA256(segredo, "<t>.<corpo bruto>"). O segredo (whsec_…) fica em Minha conta → API. Verifique sempre com o corpo bruto e recuse assinaturas com mais de 300 s.
Laravel (rota em routes/api.php, fora do CSRF):
use Convertaja\SignatureVerificationException; use Convertaja\Webhook; use Illuminate\Http\Request; Route::post('/webhooks/convertaja', function (Request $request) { try { $event = Webhook::constructEvent( $request->getContent(), // corpo bruto $request->header('X-Convertaja-Signature'), config('services.convertaja.webhook_secret'), ); } catch (SignatureVerificationException $e) { abort(400, 'assinatura inválida'); } match ($event['type']) { 'job.completed' => ProcessarTarefa::dispatch($event['data']), // id, outputs, download_url… 'esign.envelope.completed' => ArquivarContrato::dispatch($event['data']), default => null, }; return response()->noContent(); // responda 2xx rápido; o Convertajá tenta até 3 vezes });
PHP puro:
$raw = file_get_contents('php://input'); if (!\Convertaja\Webhook::verify($raw, $_SERVER['HTTP_X_CONVERTAJA_SIGNATURE'] ?? null, getenv('CONVERTAJA_WEBHOOK_SECRET'))) { http_response_code(400); exit; } $event = json_decode($raw, true);
Use o cabeçalho X-Convertaja-Delivery para descartar entregas repetidas.
Erros
Toda falha vira Convertaja\ConvertajaException:
use Convertaja\ConvertajaException; try { $cj->tools->run('comprimir-pdf', ['files' => ['grande.pdf']]); } catch (ConvertajaException $e) { echo $e->getStatus(); // 402 (também em getCode()) echo $e->getErrorCode(); // 'insufficient_credits' (estável, para tratar no código) echo $e->getMessage(); // mensagem em português echo $e->getRequestId(); // informe ao suporte print_r($e->details); // corpo de erro completo (ex.: credits_required) }
Códigos do SDK, além dos da API: network_error, timeout, wait_timeout (em jobs->wait), missing_api_key, invalid_signature. Lista completa em /api/docs.
Novas tentativas e idempotência
- Repete até
max_retriesvezes (padrão 2) em falha de rede, tempo esgotado, 408, 429 (excetotest_limitereminder_too_soon), 5xx e 409idempotency_in_progress. - Em 429 espera o
Retry-Afterda API (até 60 s); nos outros casos usa recuo exponencial (0,5 s, 1 s, 2 s… até 8 s). - Todo POST leva uma
Idempotency-Key(UUID v4) gerada uma vez por chamada e repetida em todas as tentativas: se a primeira chegou a ser processada, a repetição devolve a mesma resposta, sem novo débito. - Para repetir com segurança entre processos (ex.: fila do Laravel), passe a sua chave:
$cj->tools->run('comprimir-pdf', ['files' => [...], 'idempotency_key' => 'pedido-' . $pedido->id]). A mesma chave com outro conteúdo em 24 h dá 409idempotency_key_reused. - Depois de cada chamada:
$cj->creditsRemaining(),$cj->lastRateLimit,$cj->lastRequestIde$cj->lastResponse(status,attempts,idempotency_key,replayed).
Testes
composer install vendor/bin/phpunit # sobe php -S 127.0.0.1 com tests/mock-router.php; nenhuma chamada sai da máquina php tests/smoke.php # verificação rápida sem PHPUnit
Licença
MIT