This quickstart walks you through creating your first signed fiscal record with fiskaly SIGN FR, fulfilling the three key French fiscal obligations: signing, journaling, and archiving.
Prerequisites
Section titled “Prerequisites”- A fiskaly account (sign up at hub.fiskaly.com)
- An API Key and Secret for a GROUP organization in the TEST environment
- Taxpayer information: company name, SIREN number, address
⚠️Store credentials securely
Your API Secret is shown only once. Store it immediately in a secure location.
Authenticate
curl -X POST https://test.api.fiskaly.com/tokens \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-02-03" \ -H "X-Idempotency-Key: $(uuidgen)" \\ -d '{ "content": { "type": "API_KEY", "key": "YOUR_API_KEY", "secret": "YOUR_API_SECRET" } }'const BASE = "https://test.api.fiskaly.com"; const API_VERSION = "2026-02-03"; const authResp = await fetch(`${BASE}/tokens`, { method: "POST", headers: { "Content-Type": "application/json", "X-Api-Version": API_VERSION, "X-Idempotency-Key": crypto.randomUUID(), }, body: JSON.stringify({ content: { type: "API_KEY", key: "YOUR_API_KEY", secret: "YOUR_API_SECRET" }, }), }); const auth = await authResp.json(); const access_token = auth.content.authentication.bearer; 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-02-03" 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, "X-Idempotency-Key": str(uuid.uuid4())}) access_token = auth.json()["content"]["authentication"]["bearer"] hdrs = {"Authorization": f"Bearer {access_token}", "X-Api-Version": API_VERSION}// POST https://test.api.fiskaly.com/tokens // Headers: X-Api-Version: 2026-02-03, X-Idempotency-Key: <uuid> // Body: {"content":{"type":"API_KEY","key":"...","secret":"..."}}using var client = new HttpClient(); client.DefaultRequestHeaders.Add("X-Api-Version", "2026-02-03"); client.DefaultRequestHeaders.Add("X-Idempotency-Key", Guid.NewGuid().ToString()); 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 FR uses the same API platform as SIGN IT. All requests require the
X-Api-Versionheader. Write operations also needX-Idempotency-Key.Create Organization, Taxpayer, Location, and System
The setup follows the same pattern as SIGN IT — create a UNIT organization, then a Taxpayer, Location, and System, commissioning each resource:
# Create Organization UNIT curl -X POST https://test.api.fiskaly.com/organizations \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-02-03" \ -H "X-Idempotency-Key: $(uuidgen)" \ -d '{"content": {"type": "UNIT", "name": "My French Company"}}' # Create Subject API Key for the UNIT, re-authenticate, then: # Create Taxpayer curl -X POST https://test.api.fiskaly.com/taxpayers \ -H "Authorization: Bearer ${UNIT_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-02-03" \ -H "X-Idempotency-Key: $(uuidgen)" \ -d '{ "content": { "type": "COMPANY", "name": {"legal": "Ma Societe SARL", "trade": "Ma Societe"}, "address": { "line": {"type": "STREET_NUMBER", "street": "Rue de Rivoli", "number": "1"}, "code": "75001", "city": "Paris", "country": "FR" }, "fiscalization": { "type": "FR", "tax_id_number": "123456789", "credentials": { "type": "LNE", "properties": {"legal_form": "SARL", "naf_ape_code": "1071C", "social_capital": "50000"} } } } }' # Commission Taxpayer, create + commission Location and System # (same pattern as SIGN IT — see full integration guide)// Create Organization UNIT const org = await fetch(`${BASE}/organizations`, { method: "POST", headers: { ...headers, "X-Idempotency-Key": crypto.randomUUID() }, body: JSON.stringify({ content: { type: "UNIT", name: "My French Company" } }), }).then(r => r.json()); // After creating Subject API Key and re-authenticating: // 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: "Ma Societe SARL", trade: "Ma Societe" }, address: { line: { type: "STREET_NUMBER", street: "Rue de Rivoli", number: "1" }, code: "75001", city: "Paris", country: "FR", }, fiscalization: { type: "FR", tax_id_number: "123456789", credentials: { type: "LNE", properties: { legal_form: "SARL", naf_ape_code: "1071C", social_capital: "50000" }, }, }, }, }), }).then(r => r.json()); // Commission Taxpayer → create Location → commission → create System → commission# Create Taxpayer (after org + subject setup) taxpayer = requests.post(f"{BASE}/taxpayers", headers={ **hdrs, "X-Idempotency-Key": str(uuid.uuid4()) }, json={"content": { "type": "COMPANY", "name": {"legal": "Ma Societe SARL", "trade": "Ma Societe"}, "address": { "line": {"type": "STREET_NUMBER", "street": "Rue de Rivoli", "number": "1"}, "code": "75001", "city": "Paris", "country": "FR", }, "fiscalization": { "type": "FR", "tax_id_number": "123456789", "credentials": { "type": "LNE", "properties": {"legal_form": "SARL", "naf_ape_code": "1071C", "social_capital": "50000"}, }, }, }}).json() # Commission, then create + commission Location and System...// Same pattern as SIGN IT: // POST /organizations → UNIT // POST /subjects → API_KEY (scoped) // POST /tokens → re-authenticate // POST /taxpayers → FR fiscalization // PATCH /taxpayers/{id} → COMMISSIONED // POST /locations → BRANCH // POST /systems → FISCAL_DEVICE// Same pattern as SIGN IT — create and commission: // Organization → Taxpayer → Location → System // French-specific: fiscalization.type = "FR", tax_id_number = SIREN (9 digits)Create your first Record
# Part A: Intention curl -X POST https://test.api.fiskaly.com/records \ -H "Authorization: Bearer ${UNIT_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-02-03" \ -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 ${UNIT_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 2026-02-03" \ -H "X-Idempotency-Key: $(uuidgen)" \ -d '{ "content": { "type": "TRANSACTION", "record": {"id": "INTENTION_ID"}, "operation": { "type": "RECEIPT", "document": { "number": "0001", "total_vat": { "amount": "2.00", "exclusive": "10.00", "inclusive": "12.00" } }, "entries": [{ "type": "SALE", "details": {"concept": "GOOD"}, "data": { "type": "ITEM", "text": "Product A", "unit": { "quantity": "1.00", "price": {"inclusive": "12.00", "exclusive": "10.00"} }, "value": {"base": "10.00", "discount": "0.00"}, "vat": { "type": "VAT_RATE", "code": "STANDARD", "percentage": "20.00", "exclusive": "10.00", "inclusive": "12.00", "amount": "2.00" } } }], "payments": [{"type": "CASH", "details": {"amount": "12.00"}}] } } }'// 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.content.id }, operation: { type: "RECEIPT", document: { number: "0001", total_vat: { amount: "2.00", exclusive: "10.00", inclusive: "12.00" }, }, entries: [{ type: "SALE", details: { concept: "GOOD" }, data: { type: "ITEM", text: "Product A", unit: { quantity: "1.00", price: { inclusive: "12.00", exclusive: "10.00" } }, value: { base: "10.00", discount: "0.00" }, vat: { type: "VAT_RATE", code: "STANDARD", percentage: "20.00", exclusive: "10.00", inclusive: "12.00", amount: "2.00", }, }, }], payments: [{ type: "CASH", details: { amount: "12.00" } }], }, }, }), }).then(r => r.json()); console.log("Record created and archived:", record.content.state);# 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["content"]["id"]}, "operation": { "type": "RECEIPT", "document": {"number": "0001", "total_vat": {"amount": "2.00", "exclusive": "10.00", "inclusive": "12.00"}}, "entries": [{"type": "SALE", "details": {"concept": "GOOD"}, "data": { "type": "ITEM", "text": "Product A", "unit": {"quantity": "1.00", "price": {"inclusive": "12.00", "exclusive": "10.00"}}, "value": {"base": "10.00", "discount": "0.00"}, "vat": {"type": "VAT_RATE", "code": "STANDARD", "percentage": "20.00", "exclusive": "10.00", "inclusive": "12.00", "amount": "2.00"}}}], "payments": [{"type": "CASH", "details": {"amount": "12.00"}}], }, }}).json()// POST /records → INTENTION (system.id, operation.type = TRANSACTION) // POST /records → TRANSACTION (record.id = intention ID, receipt data with entries) // Data is signed, journaled, and archived for NF525 compliance// Two-step record creation: INTENTION → TRANSACTION // French VAT rate: 20.00% (standard) // Response confirms signing, journaling, and archivingOnce created, the data is automatically signed, journaled, and archived — fulfilling the three key NF525 fiscal obligations.