Exemplos de Código
Exemplos completos de integração com o Connect em várias linguagens. Cada exemplo inclui todos os endpoints da API v2.
TypeScript / Node.js — Cliente Completo
const API_KEY = "feak_bfc76ba48c0c286c9ce4bb2fcd7e178a399e329c59e529776bb5e01b0bfe8712";
const GATEWAY_URL = "https://connect.factflexi.com";
interface Empresa {
nif: string;
privateKey: string;
}
class GatewayClient {
constructor(
private apiKey: string = API_KEY,
private baseUrl: string = GATEWAY_URL,
) {}
private async request(path: string, body: Record<string, any>) {
const res = await fetch(`${this.baseUrl}${path}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": this.apiKey,
},
body: JSON.stringify(body),
});
const data = await res.json();
if (!data.success) throw new Error(`[${data.code}] ${data.error}`);
return data;
}
// Séries
async listarSeries(empresa: Empresa) {
return this.request("/v2/series", empresa);
}
async solicitarSerie(
empresa: Empresa,
tipo: string,
ano: string,
) {
return this.request("/v2/series/solicitar", {
...empresa,
seriesYear: ano,
documentType: tipo,
establishmentNumber: "SEDE",
seriesContingencyIndicator: "N",
});
}
// Documentos
async emitirDocumento(empresa: Empresa & { companyName: string }, payload: any) {
return this.request("/v2/documentos/emitir", {
nif: empresa.nif,
privateKey: empresa.privateKey,
companyName: empresa.companyName,
...payload,
});
}
async consultarEstado(empresa: Empresa, requestId: string) {
return this.request("/v2/documentos/status", {
...empresa,
requestId,
});
}
// High-level: emitir e aguardar validação
async emitirEAguardar(
empresa: Empresa & { companyName: string },
payload: any,
maxTentativas = 10,
) {
const { requestIdAGT } = await this.emitirDocumento(empresa, payload);
console.log(`Submetido. requestIdAGT: ${requestIdAGT}`);
for (let i = 0; i < maxTentativas; i++) {
await new Promise((r) => setTimeout(r, 3000));
const estado = await this.consultarEstado(empresa, requestIdAGT);
if (estado.resultCode === "7" || estado.resultCode === "8") {
console.log(`Tentativa ${i + 1}: ${estado.resultado}`);
continue;
}
return estado;
}
throw new Error("Timeout: validacao ainda em curso");
}
}
// ─── Uso ───
const client = new GatewayClient();
const empresa = {
nif: "5000537039",
privateKey: "-----BEGIN PRIVATE KEY-----\n...",
};
// Listar séries
const { series } = await client.listarSeries(empresa);
console.log(`${series.length} séries encontradas`);
// Criar série FT 2026 (se necessário)
const { serie } = await client.solicitarSerie(empresa, "FT", "2026");
console.log(`Série criada: ${serie.codigo}`);
// Emitir factura e aguardar validação
const resultado = await client.emitirEAguardar(
{ ...empresa, companyName: "SONHE TESTE" },
{
documentos: [{
numero: `FT ${serie.codigo}/1`,
tipo: "FT",
data: "2026-07-25",
cliente: { nome: "Cliente", nif: "999999999", pais: "AO" },
itens: [{
codigo: "PROD001", descricao: "Produto",
quantidade: 2, unidade: "UN", precoUnitario: 5000, taxa: 14,
}],
}],
},
);
console.log(`Resultado: ${resultado.resultado}`);
for (const doc of resultado.documentos) {
console.log(` ${doc.status === "valido" ? "✅" : "❌"} ${doc.numero}`);
} Python — Cliente Completo
import requests
import time
API_KEY = "feak_bfc76ba48c0c286c9ce4bb2fcd7e178a399e329c59e529776bb5e01b0bfe8712"
GATEWAY_URL = "https://connect.factflexi.com"
class GatewayClient:
def __init__(self, api_key: str = API_KEY, base_url: str = GATEWAY_URL):
self.api_key = api_key
self.base_url = base_url
self.headers = {
"Content-Type": "application/json",
"x-api-key": api_key,
}
def _request(self, path: str, body: dict) -> dict:
res = requests.post(f"{self.base_url}{path}", json=body, headers=self.headers)
data = res.json()
if not data.get("success"):
raise Exception(f"[{data.get('code')}] {data.get('error')}")
return data
# ── Séries ──
def listar_series(self, nif: str, private_key: str) -> dict:
return self._request("/v2/series", {"nif": nif, "privateKey": private_key})
def solicitar_serie(self, nif: str, private_key: str, tipo: str, ano: str) -> dict:
return self._request("/v2/series/solicitar", {
"nif": nif,
"privateKey": private_key,
"seriesYear": ano,
"documentType": tipo,
"establishmentNumber": "SEDE",
"seriesContingencyIndicator": "N",
})
# ── Documentos ──
def emitir_documento(self, nif: str, private_key: str, company_name: str, payload: dict) -> dict:
return self._request("/v2/documentos/emitir", {
"nif": nif,
"privateKey": private_key,
"companyName": company_name,
**payload,
})
def consultar_estado(self, nif: str, private_key: str, request_id: str) -> dict:
return self._request("/v2/documentos/status", {
"nif": nif,
"privateKey": private_key,
"requestId": request_id,
})
# ── High-level ──
def emitir_e_aguardar(self, nif: str, private_key: str, company_name: str,
payload: dict, max_tentativas: int = 10) -> dict:
resultado = self.emitir_documento(nif, private_key, company_name, payload)
request_id = resultado["requestIdAGT"]
print(f"Submetido. requestIdAGT: {request_id}")
for i in range(max_tentativas):
time.sleep(3)
estado = self.consultar_estado(nif, private_key, request_id)
if estado["resultCode"] in ("7", "8"):
print(f"Tentativa {i + 1}: {estado['resultado']}")
continue
return estado
raise Exception("Timeout: validacao ainda em curso")
# ─── Uso ───
client = GatewayClient()
# Listar séries
series_data = client.listar_series("5000537039", "-----BEGIN PRIVATE KEY-----\n...")
print(f"{series_data['total']} séries encontradas")
# Emitir factura e aguardar
estado = client.emitir_e_aguardar(
"5000537039",
"-----BEGIN PRIVATE KEY-----\n...",
"SONHE TESTE",
{
"documentos": [{
"numero": "FT FT3926S9043N/10",
"tipo": "FT",
"data": "2026-07-25",
"cliente": {"nome": "Cliente", "nif": "999999999", "pais": "AO"},
"itens": [{
"codigo": "PROD001", "descricao": "Produto",
"quantidade": 2, "unidade": "UN",
"precoUnitario": 5000, "taxa": 14,
}],
}],
},
)
print(f"Resultado: {estado['resultado']}")
for doc in estado["documentos"]:
icon = "✅" if doc["status"] == "valido" else "❌"
print(f" {icon} {doc['numero']}") PHP — Cliente Completo
<?php
class GatewayClient {
private string $apiKey;
private string $baseUrl;
public function __construct(
string $apiKey = 'feak_bfc76ba48c0c286c9ce4bb2fcd7e178a399e329c59e529776bb5e01b0bfe8712',
string $baseUrl = 'https://connect.factflexi.com'
) {
$this->apiKey = $apiKey;
$this->baseUrl = $baseUrl;
}
private function request(string $path, array $body): array {
$ch = curl_init("{$this->baseUrl}{$path}");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'x-api-key: ' . $this->apiKey,
],
CURLOPT_POSTFIELDS => json_encode($body),
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if (!$data['success']) {
throw new Exception("[{$data['code']}] {$data['error']}");
}
return $data;
}
// ── Séries ──
public function listarSeries(string $nif, string $privateKey): array {
return $this->request('/v2/series', [
'nif' => $nif,
'privateKey' => $privateKey,
]);
}
public function solicitarSerie(
string $nif, string $privateKey,
string $tipo, string $ano
): array {
return $this->request('/v2/series/solicitar', [
'nif' => $nif,
'privateKey' => $privateKey,
'seriesYear' => $ano,
'documentType' => $tipo,
'establishmentNumber' => 'SEDE',
'seriesContingencyIndicator' => 'N',
]);
}
// ── Documentos ──
public function emitirDocumento(
string $nif, string $privateKey,
string $companyName, array $payload
): array {
return $this->request('/v2/documentos/emitir', array_merge([
'nif' => $nif,
'privateKey' => $privateKey,
'companyName' => $companyName,
], $payload));
}
public function consultarEstado(
string $nif, string $privateKey, string $requestId
): array {
return $this->request('/v2/documentos/status', [
'nif' => $nif,
'privateKey' => $privateKey,
'requestId' => $requestId,
]);
}
// ── High-level ──
public function emitirEAguardar(
string $nif, string $privateKey, string $companyName,
array $payload, int $maxTentativas = 10
): array {
$resultado = $this->emitirDocumento($nif, $privateKey, $companyName, $payload);
$requestId = $resultado['requestIdAGT'];
echo "Submetido. requestIdAGT: {$requestId}\n";
for ($i = 0; $i < $maxTentativas; $i++) {
sleep(3);
$estado = $this->consultarEstado($nif, $privateKey, $requestId);
if (in_array($estado['resultCode'], ['7', '8'])) {
echo "Tentativa " . ($i + 1) . ": {$estado['resultado']}\n";
continue;
}
return $estado;
}
throw new Exception("Timeout: validacao ainda em curso");
}
}
// ─── Uso ───
$client = new GatewayClient();
// Listar séries
$seriesData = $client->listarSeries('5000537039', "-----BEGIN PRIVATE KEY-----\n...");
echo "{$seriesData['total']} séries encontradas\n";
// Emitir factura e aguardar
$estado = $client->emitirEAguardar(
'5000537039',
"-----BEGIN PRIVATE KEY-----\n...",
'SONHE TESTE',
[
'documentos' => [[
'numero' => 'FT FT3926S9043N/15',
'tipo' => 'FT',
'data' => '2026-07-25',
'cliente' => ['nome' => 'Cliente', 'nif' => '999999999', 'pais' => 'AO'],
'itens' => [[
'codigo' => 'PROD001', 'descricao' => 'Produto',
'quantidade' => 2, 'unidade' => 'UN',
'precoUnitario' => 5000, 'taxa' => 14,
]],
]],
],
);
echo "Resultado: {$estado['resultado']}\n";
foreach ($estado['documentos'] as $doc) {
$icon = $doc['status'] === 'valido' ? '✅' : '❌';
echo " {$icon} {$doc['numero']}\n";
} cURL — Receitas Rápidas
Listar séries
curl -s -X POST https://connect.factflexi.com/v2/series
-H "Content-Type: application/json"
-H "x-api-key: feak_..."
-d '{"nif":"5000537039","privateKey":"-----BEGIN PRIVATE KEY-----\n..."}' Solicitar série FT 2026
curl -s -X POST https://connect.factflexi.com/v2/series/solicitar
-H "Content-Type: application/json"
-H "x-api-key: feak_..."
-d '{"nif":"5000537039","privateKey":"...","seriesYear":"2026","documentType":"FT","establishmentNumber":"SEDE","seriesContingencyIndicator":"N"}' Emitir factura
curl -s -X POST https://connect.factflexi.com/v2/documentos/emitir
-H "Content-Type: application/json"
-H "x-api-key: feak_..."
-d '{"nif":"5000537039","privateKey":"...","companyName":"SONHE TESTE","documentos":[{"numero":"FT FT3926S9043N/1","tipo":"FT","data":"2026-07-25","cliente":{"nome":"Cliente","nif":"999999999","pais":"AO"},"itens":[{"codigo":"P001","descricao":"Produto","quantidade":2,"unidade":"UN","precoUnitario":5000,"taxa":14}]}]}' Consultar estado
curl -s -X POST https://connect.factflexi.com/v2/documentos/status
-H "Content-Type: application/json"
-H "x-api-key: feak_..."
-d '{"nif":"5000537039","privateKey":"...","requestId":"202600002471491"}'