Inicio rápido Portugal
Este inicio rápido cubre los pasos esenciales para comenzar con la API de SIGN PT, desde la autenticación hasta la creación de su primer registro fiscal. Para una guía más detallada, consulte nuestra guía de integración.
Requisitos previos
Sección titulada «Requisitos previos»- Una cuenta fiskaly (regístrese en hub.fiskaly.com)
- Una clave de API y Secret para una Organización
GROUPen el entorno TEST - Credenciales de subusuario del AT Portal das Finanças para el contribuyente (credenciales reales requeridas solo en LIVE)
Su API Secret se muestra solo una vez. Guárdelo inmediatamente en un lugar seguro.
Autenticarse
curl -X POST https://test.api.fiskaly.com/tokens \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-05-04" \ -d '{ "content": { "type": "API_KEY", "key": "YOUR_API_KEY", "secret": "YOUR_API_SECRET" } }'const BASE = "https://test.api.fiskaly.com"; const API_VERSION = "2026-05-04"; const authResp = await fetch(`${BASE}/tokens`, { method: "POST", headers: { "Content-Type": "application/json", "X-Api-Version": API_VERSION, }, body: JSON.stringify({ content: { type: "API_KEY", key: "YOUR_API_KEY", secret: "YOUR_API_SECRET" }, }), }); const { access_token } = await authResp.json(); const headers = { "Authorization": `Bearer ${access_token}`, "Content-Type": "application/json", "X-Api-Version": API_VERSION, };import requests, uuid BASE = "https://test.api.fiskaly.com" API_VERSION = "2026-05-04" auth = requests.post(f"{BASE}/tokens", json={ "content": {"type": "API_KEY", "key": "YOUR_API_KEY", "secret": "YOUR_API_SECRET"} }, headers={"X-Api-Version": API_VERSION}) access_token = auth.json()["access_token"] hdrs = {"Authorization": f"Bearer {access_token}", "X-Api-Version": API_VERSION}// POST https://test.api.fiskaly.com/tokens // Headers: Content-Type: application/json, X-Api-Version: 2026-05-04 // Body: {"content":{"type":"API_KEY","key":"...","secret":"..."}}using var client = new HttpClient(); client.DefaultRequestHeaders.Add("X-Api-Version", "2026-05-04"); var authResp = await client.PostAsJsonAsync( "https://test.api.fiskaly.com/tokens", new { content = new { type = "API_KEY", key = "YOUR_API_KEY", secret = "YOUR_API_SECRET" } });📘NoteSIGN PT utiliza la misma plataforma de API unificada que SIGN IT y SIGN FR. Todas las solicitudes requieren el encabezado
X-Api-Version. Las operaciones de escritura también necesitan un encabezadoX-Idempotency-Keycon un valor UUIDv3 o UUIDv4.Crear una Organización
UNITcurl -X POST https://test.api.fiskaly.com/organizations \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-05-04" \ -H "X-Idempotency-Key: $(uuidgen)" \ -d '{ "content": { "type": "UNIT", "name": "My Portuguese Merchant" } }'const org = await fetch(`${BASE}/organizations`, { method: "POST", headers: { ...headers, "X-Idempotency-Key": crypto.randomUUID() }, body: JSON.stringify({ content: { type: "UNIT", name: "My Portuguese Merchant" }, }), }).then(r => r.json()); const orgId = org.id;org = requests.post(f"{BASE}/organizations", headers={ **hdrs, "X-Idempotency-Key": str(uuid.uuid4()) }, json={"content": {"type": "UNIT", "name": "My Portuguese Merchant"}}).json() org_id = org["id"]// POST /organizations // Headers: X-Idempotency-Key: <uuid> // Body: {"content":{"type":"UNIT","name":"My Portuguese Merchant"}}client.DefaultRequestHeaders.Add("X-Idempotency-Key", Guid.NewGuid().ToString()); var org = await client.PostAsJsonAsync($"{BASE}/organizations", new { content = new { type = "UNIT", name = "My Portuguese Merchant" } });Crear una clave de API de sujeto y autenticarse
Cree una clave de API para la
UNITy autentíquese con ella:# Create Subject API Key (scoped to the `UNIT`) curl -X POST https://test.api.fiskaly.com/subjects \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-05-04" \ -H "X-Idempotency-Key: $(uuidgen)" \ -H "X-Scope-Identifier: ${ORG_ID}" \ -d '{"content": {"type": "API_KEY"}}' # Authenticate with the new API Key curl -X POST https://test.api.fiskaly.com/tokens \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-05-04" \ -d '{"content": {"type": "API_KEY", "key": "NEW_KEY", "secret": "NEW_SECRET"}}'// Create Subject API Key scoped to the `UNIT` const subject = await fetch(`${BASE}/subjects`, { method: "POST", headers: { ...headers, "X-Idempotency-Key": crypto.randomUUID(), "X-Scope-Identifier": orgId, }, body: JSON.stringify({ content: { type: "API_KEY" } }), }).then(r => r.json()); // Re-authenticate with the new key const newAuth = await fetch(`${BASE}/tokens`, { method: "POST", headers: { "Content-Type": "application/json", "X-Api-Version": API_VERSION, }, body: JSON.stringify({ content: { type: "API_KEY", key: subject.key, secret: subject.secret }, }), }).then(r => r.json()); headers.Authorization = `Bearer ${newAuth.access_token}`;# Create Subject API Key subject = requests.post(f"{BASE}/subjects", headers={ **hdrs, "X-Idempotency-Key": str(uuid.uuid4()), "X-Scope-Identifier": org_id, }, json={"content": {"type": "API_KEY"}}).json() # Re-authenticate new_auth = requests.post(f"{BASE}/tokens", headers={"X-Api-Version": API_VERSION}, json={"content": {"type": "API_KEY", "key": subject["key"], "secret": subject["secret"]}}).json() hdrs["Authorization"] = f"Bearer {new_auth['access_token']}"// POST /subjects with X-Scope-Identifier: <orgId> // Body: {"content":{"type":"API_KEY"}} // Then POST /tokens with the new key and secret// Create Subject API Key, then re-authenticate with the new credentials // POST /subjects → returns key + secret // POST /tokens → returns new access_tokenCrear Contribuyente, Ubicación y Sistema
⚠️Se requiere subusuario del AT Portal das FinançasSIGN PT llama a los servicios web de AT en nombre del contribuyente. Antes de crear un Contribuyente en LIVE, el comerciante debe crear un subusuario de servicio web dedicado en el Portal das Finanças con los permisos WSE, WFA y WDT (cuando corresponda) y aceptar los términos y condiciones de AT. En TEST se aceptan credenciales de marcador de posición.
# Create Taxpayer curl -X POST https://test.api.fiskaly.com/taxpayers \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-05-04" \ -H "X-Idempotency-Key: $(uuidgen)" \ -d '{ "content": { "type": "COMPANY", "name": { "legal": "Minha Empresa Lda." }, "address": { "line": { "type": "STREET_NUMBER", "street": "Rua Augusta", "number": "28" }, "code": "1100-053", "city": "Lisboa", "country": "PT" }, "fiscalization": { "type": "PT", "tax_id_number": "512345678", "email": "fiscal@minhaempresa.pt", "registration": { "capital": "50000.00", "office": "CRC Lisboa", "other": "sob NIF 512345678" }, "credentials": { "type": "AT", "username": "512345678/3", "password": "YOUR_AT_PASSWORD" } } } }' # Commission Taxpayer curl -X PATCH "https://test.api.fiskaly.com/taxpayers/${TAXPAYER_ID}" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-05-04" \ -H "X-Idempotency-Key: $(uuidgen)" \ -d '{"content": {"state": "COMMISSIONED"}}'// Create Taxpayer const taxpayer = await fetch(`${BASE}/taxpayers`, { method: "POST", headers: { ...headers, "X-Idempotency-Key": crypto.randomUUID() }, body: JSON.stringify({ content: { type: "COMPANY", name: { legal: "Minha Empresa Lda." }, address: { line: { type: "STREET_NUMBER", street: "Rua Augusta", number: "28" }, code: "1100-053", city: "Lisboa", country: "PT", }, fiscalization: { type: "PT", tax_id_number: "512345678", email: "fiscal@minhaempresa.pt", registration: { capital: "50000.00", office: "CRC Lisboa", other: "sob NIF 512345678", }, credentials: { type: "AT", username: "512345678/3", password: "YOUR_AT_PASSWORD", }, }, }, }), }).then(r => r.json()); // Commission Taxpayer await fetch(`${BASE}/taxpayers/${taxpayer.id}`, { method: "PATCH", headers: { ...headers, "X-Idempotency-Key": crypto.randomUUID() }, body: JSON.stringify({ content: { state: "COMMISSIONED" } }), }); // Create + Commission Location and System follow the same pattern# Create Taxpayer taxpayer = requests.post(f"{BASE}/taxpayers", headers={ **hdrs, "X-Idempotency-Key": str(uuid.uuid4()) }, json={"content": { "type": "COMPANY", "name": {"legal": "Minha Empresa Lda."}, "address": { "line": {"type": "STREET_NUMBER", "street": "Rua Augusta", "number": "28"}, "code": "1100-053", "city": "Lisboa", "country": "PT", }, "fiscalization": { "type": "PT", "tax_id_number": "512345678", "email": "fiscal@minhaempresa.pt", "registration": { "capital": "50000.00", "office": "CRC Lisboa", "other": "sob NIF 512345678", }, "credentials": { "type": "AT", "username": "512345678/3", "password": "YOUR_AT_PASSWORD", }, }, }}).json() # Commission Taxpayer requests.patch(f"{BASE}/taxpayers/{taxpayer['id']}", headers={ **hdrs, "X-Idempotency-Key": str(uuid.uuid4()) }, json={"content": {"state": "COMMISSIONED"}})// POST /taxpayers // Body: {"content":{"type":"COMPANY","name":{"legal":"Minha Empresa Lda."}, // "address":{"line":{"type":"STREET_NUMBER","street":"Rua Augusta","number":"28"}, // "code":"1100-053","city":"Lisboa","country":"PT"}, // "fiscalization":{"type":"PT","tax_id_number":"512345678", // "email":"fiscal@minhaempresa.pt", // "registration":{"capital":"50000.00","office":"CRC Lisboa","other":"sob NIF 512345678"}, // "credentials":{"type":"AT","username":"512345678/3","password":"YOUR_AT_PASSWORD"}}}} // PATCH /taxpayers/{id} → {"content":{"state":"COMMISSIONED"}} // POST /locations → create BRANCH, then PATCH /locations/{id} → commission // POST /systems → create FISCAL_DEVICE, then PATCH /systems/{id} → commission// POST /taxpayers → create COMPANY with PT fiscalization // fiscalization.type = "PT", tax_id_number = NIF (9 digits) // fiscalization.email = fiscal contact email // fiscalization.registration = { capital, office (CRC), other } // fiscalization.credentials = { type: "AT", username: "<NIF>/<subuser-id>", password } // PATCH /taxpayers/{id} → {"content":{"state":"COMMISSIONED"}} // Same pattern for locations and systems💡Crear primero el ContribuyenteDespués de poner en servicio el Contribuyente, cree una o varias Ubicaciones (
type: "BRANCH") y uno o varios Sistemas (type: "FISCAL_DEVICE"). Actualice cada uno aCOMMISSIONEDantes de crear Registros. Consulte la guía de integración completa para la secuencia completa.⚠️Aviso de facturaciónLa facturación comienza tan pronto como un Sistema es puesto en servicio en el entorno LIVE — momento en el que también comenzará a transmitir documentos oficiales a AT.
En el entorno TEST no se realizan cobros ni transmisiones reales.
Crear su primer Registro
Los Registros requieren dos llamadas: una INTENTION seguida de una TRANSACTION.
# Part A: Intention curl -X POST https://test.api.fiskaly.com/records \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-05-04" \ -H "X-Idempotency-Key: $(uuidgen)" \ -d '{ "content": { "type": "INTENTION", "system": {"id": "YOUR_SYSTEM_ID"}, "operation": {"type": "TRANSACTION"} } }' # Part B: Transaction curl -X POST https://test.api.fiskaly.com/records \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-05-04" \ -H "X-Idempotency-Key: $(uuidgen)" \ -d '{ "content": { "type": "TRANSACTION", "record": {"id": "YOUR_INTENTION_ID"}, "operation": { "type": "RECEIPT", "document": { "number": "FS-2026/00001", "series": "FS-2026", "total_vat": { "amount": "2.30", "exclusive": "10.00", "inclusive": "12.30" } }, "entries": [ { "type": "SALE", "data": { "type": "ITEM", "text": "Product A", "unit": {"quantity": "1.00", "price": "10.00"}, "value": {"base": "10.00"}, "vat": { "type": "VAT_RATE", "code": "STANDARD", "percentage": "23.00", "amount": "2.30", "exclusive": "10.00", "inclusive": "12.30" } }, "details": {"concept": "GOOD"} } ], "payments": [ { "type": "CASH", "details": {"amount": "12.30", "currency": "EUR"} } ] } } }'// Part A: Intention const intention = await fetch(`${BASE}/records`, { method: "POST", headers: { ...headers, "X-Idempotency-Key": crypto.randomUUID() }, body: JSON.stringify({ content: { type: "INTENTION", system: { id: systemId }, operation: { type: "TRANSACTION" }, }, }), }).then(r => r.json()); // Part B: Transaction const record = await fetch(`${BASE}/records`, { method: "POST", headers: { ...headers, "X-Idempotency-Key": crypto.randomUUID() }, body: JSON.stringify({ content: { type: "TRANSACTION", record: { id: intention.id }, operation: { type: "RECEIPT", document: { number: "FS-2026/00001", series: "FS-2026", total_vat: { amount: "2.30", exclusive: "10.00", inclusive: "12.30" }, }, entries: [{ type: "SALE", data: { type: "ITEM", text: "Product A", unit: { quantity: "1.00", price: "10.00" }, value: { base: "10.00" }, vat: { type: "VAT_RATE", code: "STANDARD", percentage: "23.00", amount: "2.30", exclusive: "10.00", inclusive: "12.30", }, }, details: { concept: "GOOD" }, }], payments: [{ type: "CASH", details: { amount: "12.30", currency: "EUR" } }], }, }, }), }).then(r => r.json()); console.log("ATCUD:", record.compliance?.atcud); console.log("QR code:", record.compliance?.qr_code);# Part A: Intention intention = requests.post(f"{BASE}/records", headers={ **hdrs, "X-Idempotency-Key": str(uuid.uuid4()) }, json={"content": { "type": "INTENTION", "system": {"id": system_id}, "operation": {"type": "TRANSACTION"}, }}).json() # Part B: Transaction record = requests.post(f"{BASE}/records", headers={ **hdrs, "X-Idempotency-Key": str(uuid.uuid4()) }, json={"content": { "type": "TRANSACTION", "record": {"id": intention["id"]}, "operation": { "type": "RECEIPT", "document": { "number": "FS-2026/00001", "series": "FS-2026", "total_vat": {"amount": "2.30", "exclusive": "10.00", "inclusive": "12.30"}, }, "entries": [{ "type": "SALE", "data": { "type": "ITEM", "text": "Product A", "unit": {"quantity": "1.00", "price": "10.00"}, "value": {"base": "10.00"}, "vat": { "type": "VAT_RATE", "code": "STANDARD", "percentage": "23.00", "amount": "2.30", "exclusive": "10.00", "inclusive": "12.30", }, }, "details": {"concept": "GOOD"}, }], "payments": [{"type": "CASH", "details": {"amount": "12.30", "currency": "EUR"}}], }, }}).json() print("ATCUD:", record.get("compliance", {}).get("atcud"))// POST /records → INTENTION: system.id, operation.type = "TRANSACTION" // POST /records → TRANSACTION: // record.id = intention ID // operation.type = "RECEIPT" // document: number "FS-2026/00001", series "FS-2026", // total_vat { amount, exclusive, inclusive } // entries[0]: type "SALE", data { type "ITEM", text, unit, value, vat { type "VAT_RATE", code "STANDARD", ... } }, // details { concept "GOOD" } // payments[0]: type "CASH", details { amount, currency "EUR" } // Response includes compliance data: ATCUD, QR code content, hash excerpt, certificate number// POST /records → INTENTION, then POST /records → TRANSACTION // Each requires X-Idempotency-Key header // TRANSACTION body: record.id (intention ID), operation.type "RECEIPT", // document { number, series, total_vat { amount, exclusive, inclusive } }, // entries[0] { type "SALE", data { type "ITEM", text, unit, value, vat { type "VAT_RATE", ... } }, details { concept "GOOD" } }, // payments[0] { type "CASH", details { amount, currency "EUR" } } // Response contains compliance data: ATCUD, QR code, hash excerptUna vez que el Registro alcanza el estado
COMPLETED, SIGN PT devuelve el payload de cumplimiento para la impresión: código ATCUD, contenido del código QR, fragmento hash y el número de certificado del software.
Próximos pasos
Sección titulada «Próximos pasos»Was this page helpful?