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.
composer require engineapi/sdk
Configuração
<?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
]);
| Chave | Tipo | Obrigatório | Descrição |
|---|---|---|---|
base_url | string | Sim | URL base da API (sem /v1) |
api_key | string | Sim* | API Key server-to-server (ek_live_/ek_test_) |
token | string | Sim* | JWT de sessão de dashboard |
timeout | float | Não | Timeout em segundos (padrão 30) |
*Use api_key OU token.
Módulos Disponíveis
$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.
$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
// 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).
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
// 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
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
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'];