Documentação
Portal do Cliente

Listar Séries

POST /v2/series

Obtém todas as séries de numeração registadas na AGT para um determinado contribuinte. Cada série define um intervalo de documentos fiscais que podem ser emitidos.

Porquê usar este endpoint? Antes de emitir documentos, precisas de saber que séries estão disponíveis. O código da série (ex: FT3926S9043N) é usado depois no endpoint de emitir documento para compor o número do documento (FT FT3926S9043N/1).


Request

Autenticação

Inclui a tua API Key num destes headers:

Authorization: Bearer feak_...

ou

x-api-key: feak_...

Scope necessário: series:listar ou *

Body (JSON)

CampoTipoObrigatórioDescrição
nifstring✅ SimNIF do contribuinte (ex: "5000537039")
privateKeystring✅ SimChave privada RSA do contribuinte em formato PEM

Response

Sucesso (200 OK)

{
  "success": true,
  "total": 2283,
  "series": [
    {
      "codigo": "FT3926S9043N",
      "ano": "2026",
      "tipoDocumento": "FT",
      "estado": "activa",
      "dataCriacao": "2026-07-25T11:44:25.500512",
      "primeiroDocumento": "1",
      "nif": "5000537039",
      "nome": "SONHE TESTE"
    }
  ]
}

Campos da Resposta

CampoTipoDescrição
successbooleantrue — pedido processado com sucesso
totalnumberNúmero total de séries encontradas
seriesarrayLista de séries de numeração
series[].codigostringCódigo único da série (ex: FT3926S9043N)
series[].anostringAno de emissão da série
series[].tipoDocumentostringTipo de documento: FT, FR, NC, ND, RC, etc.
series[].estadostring"activa" — a série está disponível para emissão
series[].dataCriacaostringData/hora de criação da série (ISO 8601)
series[].primeiroDocumentostringNúmero do primeiro documento da série
series[].nifstringNIF do contribuinte proprietário
series[].nomestringNome do contribuinte

Contribuinte sem séries

Se o NIF não tiver séries registadas, a resposta é um array vazio:

{
  "success": true,
  "total": 0,
  "series": []
}

Erros

Erros de Autenticação

HTTPcodeMensagemCausa
401UNAUTHORIZEDNao autorizado.API Key não foi enviada
401UNAUTHORIZEDAPI Key invalida.API Key não existe ou foi revogada
403FORBIDDENScope insuficiente.A key não tem o scope series:listar

Erros de Validação

HTTPcodeMensagemCausa
400INVALID_JSONBody JSON invalido.O corpo do request não é JSON válido
400VALIDATION_ERRORPayload invalido. Campos obrigatorios: nif, privateKey.Falta nif ou privateKey
400VALIDATION_ERRORToo small: expected string to have >=1 charactersnif ou privateKey vazios

Erros da AGT

HTTPcodeMensagemCausa
502AGT_ERRORsecretOrPrivateKey must be an asymmetric key when using RS256Chave privada inválida ou corrompida
502AGT_ERRORErro de comunicacao com a AGTServiço AGT indisponível

Exemplos de Código

TypeScript / Node.js

const API_KEY = "feak_bfc76ba48c0c286c9ce4bb2fcd7e178a399e329c59e529776bb5e01b0bfe8712";
const GATEWAY_URL = "https://connect.factflexi.com";

async function listarSeries(nif: string, privateKey: string) {
  const response = await fetch(`${GATEWAY_URL}/v2/series`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": API_KEY,
    },
    body: JSON.stringify({ nif, privateKey }),
  });

  const data = await response.json();

  if (!data.success) {
    throw new Error(`${data.code}: ${data.error}`);
  }

  console.log(`Encontradas ${data.total} séries para NIF ${nif}`);
  for (const s of data.series) {
    console.log(`  ${s.codigo}${s.tipoDocumento} ${s.ano}${s.estado}`);
  }

  return data.series;
}

// Uso
const series = await listarSeries("5000537039", `-----BEGIN PRIVATE KEY-----\n...`);

Python

import requests

API_KEY = "feak_bfc76ba48c0c286c9ce4bb2fcd7e178a399e329c59e529776bb5e01b0bfe8712"
GATEWAY_URL = "https://connect.factflexi.com"

def listar_series(nif: str, private_key: str):
    response = requests.post(
        f"{GATEWAY_URL}/v2/series",
        json={"nif": nif, "privateKey": private_key},
        headers={
            "Content-Type": "application/json",
            "x-api-key": API_KEY,
        },
    )
    data = response.json()

    if not data.get("success"):
        raise Exception(f"{data.get('code')}: {data.get('error')}")

    print(f"Encontradas {data['total']} séries para NIF {nif}")
    for s in data["series"]:
        print(f"  {s['codigo']}{s['tipoDocumento']} {s['ano']}{s['estado']}")

    return data["series"]

# Uso
series = listar_series("5000537039", "-----BEGIN PRIVATE KEY-----\n...")

PHP

<?php
define('API_KEY', 'feak_bfc76ba48c0c286c9ce4bb2fcd7e178a399e329c59e529776bb5e01b0bfe8712');
define('GATEWAY_URL', 'https://connect.factflexi.com');

function listarSeries(string $nif, string $privateKey): array {
    $ch = curl_init(GATEWAY_URL . '/v2/series');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'x-api-key: ' . API_KEY,
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'nif' => $nif,
            'privateKey' => $privateKey,
        ]),
        CURLOPT_RETURNTRANSFER => true,
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $data = json_decode($response, true);

    if (!$data['success']) {
        throw new Exception("{$data['code']}: {$data['error']}");
    }

    echo "Encontradas {$data['total']} séries para NIF {$nif}\n";
    foreach ($data['series'] as $s) {
        echo "  {$s['codigo']}{$s['tipoDocumento']} {$s['ano']}{$s['estado']}\n";
    }

    return $data['series'];
}

// Uso
$series = listarSeries('5000537039', "-----BEGIN PRIVATE KEY-----\n...");

Tipos de Documento

CódigoNomeCódigoNome
FTFacturaNCNota de Crédito
FRFactura/ReciboNDNota de Débito
FAFactura de AdiantamentoRCRecibo Emitido
FGFactura GlobalRGRecibo Geral
GFFactura GenéricaARAviso de Cobrança/Recibo