PHPackages                             prhost/systax-sdk - 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. [API Development](/categories/api)
4. /
5. prhost/systax-sdk

ActiveLibrary[API Development](/categories/api)

prhost/systax-sdk
=================

PHP SDK for the Systax API (NCM and CEST lookups)

v1.0.0(4mo ago)11MITPHPPHP ^8.1

Since Feb 22Pushed 4mo agoCompare

[ Source](https://github.com/prhost/systax-sdk)[ Packagist](https://packagist.org/packages/prhost/systax-sdk)[ RSS](/packages/prhost-systax-sdk/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (2)Versions (2)Used By (0)

Systax SDK — PHP
================

[](#systax-sdk--php)

> **⚠️ Aviso:** Este SDK é um projeto **não oficial** e não possui qualquer vínculo, endosso ou suporte da [Systax](https://www.systax.com). É fornecido **sem garantias de qualquer tipo**. Use por sua conta e risco.

SDK PHP para integração com a [API Systax](https://app.systax.com.br/auth/swagger#/), cobrindo os recursos de **NCM** e **CEST** (v1 e v2).

- PHP 8.1+
- GuzzleHttp 7.x
- Autenticação JWT automática (com cache e renovação)
- Credenciais de homologação embutidas como padrão

---

Índice
------

[](#índice)

- [Instalação](#instala%C3%A7%C3%A3o)
- [Instanciação](#instancia%C3%A7%C3%A3o)
- [Autenticação](#autentica%C3%A7%C3%A3o)
- [Recurso: CEST v1](#recurso-cest-v1)
- [Recurso: CEST v2](#recurso-cest-v2)
- [Recurso: NCM](#recurso-ncm)
- [DTOs de retorno](#dtos-de-retorno)
- [Tratamento de erros](#tratamento-de-erros)
- [Testes unitários](#testes-unit%C3%A1rios)
- [Estrutura de arquivos](#estrutura-de-arquivos)
- [Licença](#licen%C3%A7a)

---

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

[](#instalação)

```
composer require prhost/systax-sdk
```

**Requisitos:** PHP 8.1+ e GuzzleHttp 7.x (instalado automaticamente como dependência).

---

Instanciação
------------

[](#instanciação)

```
use Prhost\SystaxSdk\SystaxClient;

// Credenciais de homologação (padrão — superdemo.ws / systax741)
$client = new SystaxClient();

// Credenciais de produção (override)
$client = new SystaxClient(
    username: 'sua_empresa@usuario',
    password: 'sua_senha_producao',
);

// Override completo (incluindo base URL, útil para staging)
$client = new SystaxClient(
    username: 'usuario',
    password:  'senha',
    baseUrl:  'https://app.systax.com.br',
);
```

**Assinatura do construtor:**

```
new SystaxClient(
    ?string $username  = null,   // padrão: 'superdemo.ws'
    ?string $password  = null,   // padrão: 'systax741'
    ?string $baseUrl   = null,   // padrão: 'https://app.systax.com.br'
    ?ClientInterface $httpClient = null, // injeção de Guzzle customizado (testes)
)
```

---

Autenticação
------------

[](#autenticação)

O SDK gerencia o token JWT automaticamente:

1. Na primeira chamada a qualquer recurso, obtém o token via `GET /auth/access-token` com **Basic Auth**.
2. O token é cacheado em memória pelo tempo de `expires_in` (retornado pela API).
3. Quando o token está prestes a expirar (≤ 60 segundos), é renovado automaticamente via `GET /auth/refresh-token`.
4. Se a renovação falhar, um novo token é obtido com Basic Auth.

Você não precisa gerenciar tokens manualmente. Se necessário:

```
// Forçar busca de novo token
$client->getTokenManager()->fetchToken();

// Forçar renovação de token existente
$client->getTokenManager()->refreshToken();

// Invalidar cache (força nova autenticação na próxima chamada)
$client->getTokenManager()->clearToken();

// Inspecionar token atual em cache
$token = $client->getTokenManager()->getCachedToken(); // null se não autenticado
```

---

Recurso: CEST v1
----------------

[](#recurso-cest-v1)

**Endpoint:** `POST https://app.systax.com.br/cest`

Retorna os códigos CEST para um NCM informado.

### Criando itens de consulta

[](#criando-itens-de-consulta)

```
use Prhost\SystaxSdk\DTO\CestItem;

// Mínimo — apenas NCM (obrigatório)
$item = CestItem::make('39181000');

// Com todos os parâmetros opcionais
$item = CestItem::make(
    ncm:     '39181000',
    exTipi:  '01',         // Código EX da TIPI (opcional)
    uf:      'SP',         // UF de consulta (opcional; vazio = sem filtro de UF)
    data:    '2024-01-01', // Data de vigência (opcional; vazio = data atual)
    id:      '1',          // Sequencial (opcional)
);
```

### Consultando

[](#consultando)

```
$results = $client->cest()->query([
    CestItem::make('39181000'),
    CestItem::make('22089000', uf: 'SP'),
]);
```

Máximo de **100 itens por requisição**.

### Retorno: `CestResult[]`

[](#retorno-cestresult)

```
foreach ($results as $result) {
    $result->id;           // string — sequencial
    $result->ncm;          // string — NCM consultado (ex: '39181000')
    $result->exTipi;       // string — EX TIPI consultado
    $result->uf;           // string — UF consultada
    $result->data;         // string — data consultada
    $result->ncmTabela;    // string — NCM na tabela Systax (ex: '3918')
    $result->cest;         // string — código CEST (ex: '1017400')
    $result->descricao;    // string — descrição do CEST
    $result->ufTabela;     // string — UF na tabela CEST Systax
    $result->exTipiTabela; // string — EX TIPI na tabela Systax
    $result->statusCodigo; // int    — código de status (0 = sucesso)
    $result->statusMsg;    // string — mensagem de status
    $result->isSuccess();  // bool   — true se statusCodigo === 0
}
```

### Exemplo completo

[](#exemplo-completo)

```
use Prhost\SystaxSdk\SystaxClient;
use Prhost\SystaxSdk\DTO\CestItem;
use Prhost\SystaxSdk\Exceptions\ApiException;

$client = new SystaxClient();

try {
    $results = $client->cest()->query([CestItem::make('39181000')]);

    foreach ($results as $result) {
        echo "NCM: {$result->ncm} | CEST: {$result->cest} | {$result->descricao}\n";
    }
} catch (ApiException $e) {
    // Exemplo: NCM inválida, NCM sem CEST, UF inválida, etc.
    echo "Erro API [{$e->getApiCode()}]: {$e->getApiMessage()}\n";
}
```

---

Recurso: CEST v2
----------------

[](#recurso-cest-v2)

**Endpoint:** `POST https://app.systax.com.br/cestv2`

Versão 2 da API CEST. Adiciona:

- Paginação via `offset`
- Sincronização incremental via `ponteiro`
- Campos `vigenciaDe`, `vigenciaAte` por item
- Metadados de paginação no retorno (`TotalPaginas`, `totalItens`, `ultPonteiro`)

### Consultando

[](#consultando-1)

```
// Página 1 (padrão)
$response = $client->cestV2()->query([
    CestItem::make('22089000'),
]);

// Página específica
$response = $client->cestV2()->query([
    CestItem::make('22089000'),
], offset: 3);

// Com ponteiro para buscar apenas atualizações desde a última sincronização
$response = $client->cestV2()->query([
    CestItem::make('22089000', ponteiro: '20231013095117'),
]);
```

### Retorno: `CestV2Response`

[](#retorno-cestv2response)

```
$response->totalPaginas; // int    — total de páginas disponíveis
$response->totalItens;   // int    — total de itens encontrados
$response->ultPonteiro;  // string — último ponteiro da tabela (usar para próxima sync)
$response->items;        // CestV2Result[]
```

### `CestV2Result` (estende `CestResult`)

[](#cestv2result-estende-cestresult)

Todos os campos de `CestResult` mais:

```
$item->vigenciaDe;  // string — data inicial da vigência (ex: '2016-10-01')
$item->vigenciaAte; // string — data final da vigência (vazio = vigente)
$item->ponteiro;    // string — ponteiro de atualização deste item
```

### Exemplo: sincronização incremental

[](#exemplo-sincronização-incremental)

```
// Primeira sincronização — salvar ultPonteiro
$response  = $client->cestV2()->query([CestItem::make('22089000')]);
$ponteiro  = $response->ultPonteiro; // '20231114020001'

// Próxima sincronização — buscar apenas o que mudou
$response2 = $client->cestV2()->query([
    CestItem::make('22089000', ponteiro: $ponteiro),
]);

if (empty($response2->items)) {
    echo "Nenhuma atualização desde o último ponteiro.\n";
}
```

---

Recurso: NCM
------------

[](#recurso-ncm)

**Endpoint:** `GET https://app.systax.com.br/api/ncm`

Lista NCMs da tabela TIPI da Systax.

### Consultando

[](#consultando-2)

```
// Listar tudo (padrão: 100 por página)
$response = $client->ncm()->list();

// Filtrar por prefixo de NCM (2 a 8 dígitos)
$response = $client->ncm()->list(ncm: '3926');
$response = $client->ncm()->list(ncm: '39269090');

// Filtrar por EX TIPI
$response = $client->ncm()->list(ncm: '39269090', exTipi: '01');

// Filtrar por data de vigência
$response = $client->ncm()->list(vigenciaEm: '2024-01-01');

// Paginação
$response = $client->ncm()->list(ncm: '39', limit: 50, offset: 2);

// Ordenação: campo|direção
$response = $client->ncm()->list(order: ['ncm|asc', 'descricao|desc']);

// Buscar por ID interno Systax
$response = $client->ncm()->findById(1039194);
```

**Assinatura completa:**

```
$client->ncm()->list(
    ?string $ncm        = null,  // 2–8 dígitos
    ?string $exTipi     = null,
    ?string $vigenciaEm = null,  // YYYY-MM-DD
    ?int    $id         = null,  // ID interno Systax
    int     $limit      = 100,
    int     $offset     = 1,
    ?array  $order      = null,  // ex: ['ncm|asc']
): NcmResponse
```

### Retorno: `NcmResponse`

[](#retorno-ncmresponse)

```
$response->success;     // bool   — true se consulta OK
$response->message;     // string — 'ok' em caso de sucesso
$response->recordCount; // int    — total de registros retornados
$response->data;        // NcmResult[]
```

### `NcmResult`

[](#ncmresult)

```
$item->id;          // int         — ID interno Systax (ex: 1039194)
$item->ncm;         // string      — código NCM de 8 dígitos (ex: '39269090')
$item->exTipi;      // string|null — código EX TIPI (null se não houver)
$item->vigenciaDe;  // string|null — data início de vigência (ex: '2022-04-01')
$item->vigenciaAte; // string|null — data fim de vigência (null = vigente)
$item->aliquota;    // float       — alíquota IPI (ex: 14.5)
$item->descricao;   // string      — descrição da NCM
$item->nota;        // string|null — nota complementar de legislação
```

### Exemplo completo

[](#exemplo-completo-1)

```
use Prhost\SystaxSdk\SystaxClient;
use Prhost\SystaxSdk\Exceptions\AuthException;

$client = new SystaxClient();

try {
    $response = $client->ncm()->list(ncm: '3926', limit: 10);

    echo "Total: {$response->recordCount}\n";

    foreach ($response->data as $ncm) {
        echo "{$ncm->ncm} — {$ncm->descricao} | Alíquota: {$ncm->aliquota}%\n";
        if ($ncm->exTipi) {
            echo "  EX TIPI: {$ncm->exTipi}\n";
        }
    }
} catch (AuthException $e) {
    echo "Falha de autenticação: {$e->getMessage()}\n";
}
```

---

DTOs de retorno
---------------

[](#dtos-de-retorno)

ClasseArquivoDescrição`CestItem``DTO/CestItem.php`Input: item de consulta CEST`CestResult``DTO/CestResult.php`Output CEST v1 por item`CestV2Result``DTO/CestV2Result.php`Output CEST v2 por item (estende `CestResult`)`CestV2Response``DTO/CestV2Response.php`Wrapper paginado CEST v2`NcmResult``DTO/NcmResult.php`Output NCM por item`NcmResponse``DTO/NcmResponse.php`Wrapper resposta NCM`TokenResponse``DTO/TokenResponse.php`Resposta da API de token---

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

[](#tratamento-de-erros)

Todas as exceções estendem `Prhost\SystaxSdk\Exceptions\SystaxException` (que estende `RuntimeException`).

ExceçãoQuando é lançada`AuthException`HTTP 400/401 nas requisições de token ou recursos; credenciais inválidas; token expirado`ApiException`Resposta HTTP 200, mas com `codigo != 0` no item (ex: NCM inválida, NCM sem CEST)`SystaxException`Base — captura qualquer erro do SDK### Códigos de erro da API CEST

[](#códigos-de-erro-da-api-cest)

CódigoMensagem0Sucesso1NCM inválida2NCM sem CEST3UF inválida4EX TIPI inválida5Data inválida6ID inválido7Ponteiro inválido8Não existem atualizações### Exemplo de tratamento completo

[](#exemplo-de-tratamento-completo)

```
use Prhost\SystaxSdk\Exceptions\AuthException;
use Prhost\SystaxSdk\Exceptions\ApiException;
use Prhost\SystaxSdk\Exceptions\SystaxException;

try {
    $results = $client->cest()->query([CestItem::make('99999999')]);
} catch (AuthException $e) {
    // Problema de autenticação — verificar credenciais ou token
    logger()->error('Systax auth error', ['message' => $e->getMessage()]);
} catch (ApiException $e) {
    // Erro de negócio (NCM inválida, sem CEST, etc.)
    logger()->warning('Systax API error', [
        'code'    => $e->getApiCode(),
        'message' => $e->getApiMessage(),
    ]);
} catch (SystaxException $e) {
    // Qualquer outro erro do SDK
    logger()->error('Systax SDK error', ['message' => $e->getMessage()]);
}
```

---

Testes unitários
----------------

[](#testes-unitários)

Os testes usam `GuzzleHttp\Handler\MockHandler` — **nenhuma chamada real à API é feita**. São 50 testes cobrindo todos os recursos, casos de sucesso e de erro.

### Rodando os testes

[](#rodando-os-testes)

```
composer install
./vendor/bin/phpunit --testdox
```

**Saída esperada:**

```
PHPUnit 10.5.63 by Sebastian Bergmann and contributors.
Runtime: PHP 8.4.x

Cest Resource (Prhost\SystaxSdk\Tests\Unit\Resources\CestResource)
 ✔ Query returns array of cest results
 ✔ Query parses ncm and cest correctly
 ✔ Query returns multiple results for same ncm
 ✔ Query uses cached token on second call
 ✔ Cest item make builds array correctly
 ✔ Cest item omits empty fields
 ✔ Query throws api exception on ncm invalida
 ✔ Query throws api exception on ncm sem cest
 ✔ Query throws auth exception on 400
 ✔ Query throws auth exception on 401

Cest V2Resource (Prhost\SystaxSdk\Tests\Unit\Resources\CestV2Resource)
 ✔ Query returns cest v2 response
 ✔ Query parses pagination metadata
 ✔ Query parses items as cest v2 results
 ✔ Query parses cest and vigencia
 ✔ Query with custom offset
 ✔ Query with ponteiro item
 ✔ Query throws auth exception on 400
 ✔ Query throws auth exception on 401

Ncm Resource (Prhost\SystaxSdk\Tests\Unit\Resources\NcmResource)
 ✔ List returns ncm response
 ✔ List parses record count
 ✔ List parses ncm results
 ✔ List parses ncm result fields
 ✔ List parses second result with note and aliquota
 ✔ Find by id calls list with id param
 ✔ List without filters returns response
 ✔ List throws auth exception on 400
 ✔ List throws auth exception on 401

Systax Client (Prhost\SystaxSdk\Tests\Unit\SystaxClient)
 ✔ Default credentials are set
 ✔ Default base url is set
 ✔ Custom username overrides default
 ✔ Custom password overrides default
 ✔ Custom credentials pair overrides both
 ✔ Custom base url overrides default
 ✔ Base url trailing slash is stripped
 ✔ Cest returns cest resource
 ✔ Cest v2 returns cest v2 resource
 ✔ Ncm returns ncm resource
 ✔ Cest returns same instance on repeated calls
 ✔ Ncm returns same instance on repeated calls
 ✔ Cest v2 returns same instance on repeated calls
 ✔ Get credentials returns array with username password

Token Manager (Prhost\SystaxSdk\Tests\Unit\Auth\TokenManager)
 ✔ Fetch token returns token string
 ✔ Fetch token populates cache
 ✔ Fetch token throws auth exception on 401
 ✔ Fetch token throws auth exception on 400
 ✔ Fetch token throws auth exception when success false 200
 ✔ Ensure valid token does not re fetch when cached
 ✔ Clear token nullifies cache
 ✔ Refresh token fetches fresh when no cached token
 ✔ Refresh token throws auth exception on 401

OK (50 tests, 83 assertions)

```

### Localização dos testes

[](#localização-dos-testes)

```
tests/
├── Fixtures/
│   ├── auth_error_response.json   — resposta 401 simulada
│   ├── token_response.json        — resposta de token válido
│   ├── cest_response.json         — resposta CEST v1
│   ├── cestv2_response.json       — resposta CEST v2 (com paginação)
│   └── ncm_response.json          — resposta NCM
└── Unit/
    ├── Auth/
    │   └── TokenManagerTest.php   — 9 testes: fetch, cache, refresh, erros
    ├── Resources/
    │   ├── CestResourceTest.php   — 10 testes: parse, erros, cache token
    │   ├── CestV2ResourceTest.php — 8 testes: paginação, ponteiro, vigência
    │   └── NcmResourceTest.php    — 9 testes: list, findById, campos, erros
    └── SystaxClientTest.php       — 14 testes: credenciais, lazy resources

```

### Adicionando novos testes

[](#adicionando-novos-testes)

Os testes usam `GuzzleHttp\Handler\MockHandler` para interceptar as requisições HTTP. Padrão a seguir:

```
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;

$mock  = new MockHandler([
    new Response(200, [], '{"success":true,"status":"OK","token":"jwt...","expires_in":3600}'),
    new Response(200, [], file_get_contents(__DIR__ . '/../../Fixtures/cest_response.json')),
]);
$stack = HandlerStack::create($mock);
$http  = new Client(['handler' => $stack, 'http_errors' => false]);
```

A ordem das respostas no array do `MockHandler` corresponde à ordem das chamadas HTTP feitas pelo SDK (primeiro `fetchToken`, depois o recurso).

---

Estrutura de arquivos
---------------------

[](#estrutura-de-arquivos)

```
├── .gitignore
├── composer.json
├── phpunit.xml
├── src/
│   ├── SystaxClient.php
│   ├── Config.php
│   ├── Auth/
│   │   └── TokenManager.php
│   ├── DTO/
│   │   ├── CestItem.php
│   │   ├── CestResult.php
│   │   ├── CestV2Result.php
│   │   ├── CestV2Response.php
│   │   ├── NcmResult.php
│   │   ├── NcmResponse.php
│   │   └── TokenResponse.php
│   ├── Resources/
│   │   ├── CestResource.php
│   │   ├── CestV2Resource.php
│   │   └── NcmResource.php
│   └── Exceptions/
│       ├── SystaxException.php
│       ├── AuthException.php
│       └── ApiException.php
└── tests/
    ├── Fixtures/
    │   ├── token_response.json
    │   ├── auth_error_response.json
    │   ├── cest_response.json
    │   ├── cestv2_response.json
    │   └── ncm_response.json
    └── Unit/
        ├── Auth/
        │   └── TokenManagerTest.php
        ├── Resources/
        │   ├── CestResourceTest.php
        │   ├── CestV2ResourceTest.php
        │   └── NcmResourceTest.php
        └── SystaxClientTest.php

```

---

Referências
-----------

[](#referências)

- [Swagger Systax Geral](https://app.systax.com.br/auth/swagger#/)
- [Documentação API de Token](https://documentacao.systax.com.br/books/manual-da-api-de-geracao-de-token)
- [Documentação API CEST v1](https://documentacao.systax.com.br/books/api-cest)
- [Documentação API CEST v2](https://documentacao.systax.com.br/books/api-cest-v2)
- [Documentação API NCM](https://documentacao.systax.com.br/books/api-de-ncm)

---

Licença
-------

[](#licença)

[MIT](LICENSE)

---

Desenvolvido por [Kallef Alexandre](https://github.com/prhost)

###  Health Score

33

—

LowBetter than 72% of packages

Maintenance76

Regular maintenance activity

Popularity3

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

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

132d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3984760?v=4)[Kallef Alexandre](/maintainers/prhost)[@prhost](https://github.com/prhost)

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/prhost-systax-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/prhost-systax-sdk/health.svg)](https://phpackages.com/packages/prhost-systax-sdk)
```

###  Alternatives

[statamic/cms

The Statamic CMS Core Package

4.8k3.6M993](/packages/statamic-cms)[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3741.3M46](/packages/tencentcloud-tencentcloud-sdk-php)[neuron-core/neuron-ai

The PHP Agentic Framework.

2.0k656.1k39](/packages/neuron-core-neuron-ai)[eslazarev/wildberries-sdk

Wildberries OpenAPI clients (generated).

273.0k](/packages/eslazarev-wildberries-sdk)[avalara/avataxclient

Client library for Avalara's AvaTax suite of business tax calculation and processing services. Uses the REST v2 API.

528.5M7](/packages/avalara-avataxclient)[files.com/files-php-sdk

Files.com PHP SDK

2481.1k](/packages/filescom-files-php-sdk)

PHPackages © 2026

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