Search by

SDK oficial da API do Convertajá: PDF, DANFE, etiquetas ZPL, assinatura eletrônica, CNPJ, CEP, boleto e Pix.

v0.1.0 2026-10-18 04:02 UTC

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-curl e ext-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_retries vezes (padrão 2) em falha de rede, tempo esgotado, 408, 429 (exceto test_limit e reminder_too_soon), 5xx e 409 idempotency_in_progress.
  • Em 429 espera o Retry-After da 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á 409 idempotency_key_reused.
  • Depois de cada chamada: $cj->creditsRemaining(), $cj->lastRateLimit, $cj->lastRequestId e $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