engineAPIengineAPI
// referência

SDK PHP

SDK PHP oficial da engineAPI (EngineApiClient). Composer package engineapi/sdk, versão 1.0.0.

SDK PHP

O SDK PHP oficial está na versão 1.0.0 (PHP 8.1+, dependência única guzzlehttp/guzzle). Confirme a disponibilidade do pacote engineapi/sdk no Packagist antes de instalar. Se ainda não estiver publicado no seu ambiente, use a integração direta com Guzzle na seção final desta página como alternativa.

bash
composer require engineapi/sdk

Configuração

php
<?php

use EngineApi\EngineApiClient;

// Autenticação via API Key (recomendado para server-to-server)
$client = new EngineApiClient([
    'base_url' => 'https://api.engineapi.com.br', // sem /v1, o client adiciona
    'api_key'  => 'ek_live_SEU_API_KEY',
    'timeout'  => 30.0, // opcional, padrão 30s
]);
ChaveTipoObrigatórioDescrição
base_urlstringSimURL base da API (sem /v1)
api_keystringSim*API Key server-to-server (ek_live_/ek_test_)
tokenstringSim*JWT de sessão de dashboard
timeoutfloatNãoTimeout em segundos (padrão 30)

*Use api_key OU token.


Módulos Disponíveis

php
$client->nfe        // NFe: emissão, cancelamento, CC-e, download, status
$client->companies  // Empresas: ver aviso abaixo, contrato desatualizado

O pacote também expõe $client->dfe; esse módulo está fora do contrato público hoje. Não use em produção; será reativado quando a funcionalidade entrar na superfície pública.


NFe: Emitir

emitir() recebe um array associativo repassado verbatim ao corpo da requisição, use os nomes de campo reais do contrato: destinatario, items (não itens), pagamentos[] (não pagamento singular), cnpjCpf/nome/ie no destinatário.

php
$nfe = $client->nfe->emitir([
    'naturezaOperacao' => 'VENDA DE MERCADORIA',
    'destinatario' => [
        'cnpjCpf' => '99888777000100',
        'nome' => 'Cliente Exemplo SA',
        'indicadorIE' => 1,
        'endereco' => [
            'logradouro' => 'Av Brasil', 'numero' => '500',
            'bairro' => 'Centro', 'codigoMunicipio' => '3550308',
            'municipio' => 'São Paulo', 'uf' => 'SP', 'cep' => '01001000',
        ],
    ],
    'items' => [[
        'codigo' => 'PROD001',
        'descricao' => 'Camiseta Azul M', 'ncm' => '61091000',
        'cfop' => '5102', 'unidade' => 'UN', 'quantidade' => 1,
        'valorUnitario' => 89.90,
        'icms' => ['origem' => 0, 'csosn' => '400'],
    ]],
    'pagamentos' => [['forma' => '01', 'valor' => 89.90]],
]);

echo "NFe autorizada: " . $nfe['data']['accessKey'] . PHP_EOL;
echo "Status: " . $nfe['data']['status'] . PHP_EOL; // "AUTHORIZED"

issuerId é opcional no payload de NFe/NFCe: com um único emissor pode omitir; com dois ou mais, informe o issuerId (UUID) do CNPJ que deve emitir; sem ele a API responde 400.

Cancelar, CC-e e downloads

php
// Cancelar: campo justificativa, mínimo 15 caracteres
$client->nfe->cancelar('35260211222333000181550010000000011000000019',
    'Erro nos dados do destinatário informado na venda');

// Carta de Correção
$client->nfe->cartaCorrecao('35260211222333000181550010000000011000000019',
    'Corrijo o endereço do destinatário para Av Brasil, 500');

// Downloads
$pdf = $client->nfe->downloadPdf('35260211...');
file_put_contents('danfe.pdf', $pdf);

$xml = $client->nfe->downloadXml('35260211...');
file_put_contents('nfe.xml', $xml);

Companies: Empresas Emissoras

O client companies desta versão do pacote chama rotas erradas. criar(), listar(), buscar() e uploadCertificado() fazem requisições para /issuers/*, mas a API real expõe o módulo em /companies; /issuers não existe e retorna 404. O upload de certificado também está errado: o client manda {certificado, senha} em JSON, mas a rota real é multipart/form-data com o campo file. Até essa versão ser corrigida, use Guzzle diretamente para o módulo de empresas (exemplo abaixo).

php
use GuzzleHttp\Client;

$guzzle = new Client(['base_uri' => 'https://api.engineapi.com.br/v1/']);

// Cadastrar empresa
$empresa = $guzzle->post('companies', [
    'headers' => ['Authorization' => 'Bearer ' . $token],
    'json' => ['cnpj' => '11222333000181', 'name' => 'Empresa Exemplo Ltda'],
]);

// Upload de certificado: multipart, campo "file"
$guzzle->post("companies/{$issuerId}/certificate", [
    'headers' => ['Authorization' => 'Bearer ' . $token],
    'multipart' => [
        ['name' => 'file', 'contents' => fopen('certificado.pfx', 'r')],
        ['name' => 'password', 'contents' => 'senhaDoCertificado'],
    ],
]);

Login e API Keys

php
// Login: retorna {access_token, partner} segundo o client, mas o servidor real
// devolve {access_token, user: {id,email,name,partnerId,role}}. Trate `user`, não
// `partner`, ao ler o retorno.
$login = $client->login('usuario@partner.com', 'senha');

// Regenerar API Key de produção (exige subscription ACTIVE)
$client->regenerateApiKey();

// Info da key atual
$client->apiKeyInfo();

Tratamento de erros

php
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;

try {
    $nfe = $client->nfe->emitir($dados);
} catch (ClientException $e) {
    $status = $e->getResponse()->getStatusCode();
    $body = json_decode($e->getResponse()->getBody(), true);

    match ($status) {
        400 => logger()->error('Validação ou rejeição SEFAZ', $body['error']['erros'] ?? $body),
        403 => logger()->error('Sem permissão / ambiente da key incompatível', $body),
        422 => logger()->error('Emissão assistida: campo não resolvido', $body),
        429 => logger()->warning('Rate limit. Retry após Retry-After'),
        default => logger()->error("Erro {$status}", $body),
    };
} catch (ServerException $e) {
    // 500+: retry com backoff
    logger()->critical('Erro no servidor engineAPI', [
        'status' => $e->getResponse()->getStatusCode(),
    ]);
}

Não existem sefazCode/sefazMessage no corpo do erro: o formato real é RFC 7807: error.erros[] ({codigo, descricao}) para rejeição SEFAZ. Ver Erros e Rejeições.


Alternativa: integração direta com Guzzle

Se o pacote engineapi/sdk ainda não estiver disponível no seu ambiente, integre diretamente:

php
<?php

use GuzzleHttp\Client;

class EngineAPI
{
    private Client $client;

    public function __construct(string $baseUrl, string $apiKey)
    {
        $this->client = new Client([
            'base_uri' => rtrim($baseUrl, '/') . '/v1/',
            'headers' => [
                'x-api-key' => $apiKey,
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
            ],
            'timeout' => 30,
        ]);
    }

    public function emitirNfe(array $dados): array
    {
        $response = $this->client->post('nfe', ['json' => $dados]);
        return json_decode($response->getBody(), true);
    }

    public function cancelarNfe(string $idOuChave, string $justificativa): array
    {
        $response = $this->client->post("nfe/{$idOuChave}/cancelar", [
            'json' => ['justificativa' => $justificativa],
        ]);
        return json_decode($response->getBody(), true);
    }
}

$engine = new EngineAPI('https://api.engineapi.com.br', 'ek_live_SEU_API_KEY');
$nfe = $engine->emitirNfe([/* payload real, ver /guides/emitir-nfe */]);
echo "NFe autorizada: " . $nfe['data']['accessKey'];

Próximos passos