{
  "info": {
    "name": "Fatoora API Keys — DigiGO / SEAL / Trust",
    "description": "Collection pour les clients disposant d'une clé API (DigiGO, SEAL Max, Fatoora Trust) : créer, valider, signer et envoyer des factures TEIF à TTN.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://business.fatoora.tn",
      "type": "string"
    },
    {
      "key": "client_id",
      "value": "svc_org_sample00000000",
      "type": "string"
    },
    {
      "key": "client_secret",
      "value": "YOUR_CLIENT_SECRET_HERE",
      "type": "string"
    },
    {
      "key": "access_token",
      "value": "",
      "type": "string"
    },
    {
      "key": "invoice_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "job_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "seller_tax_id",
      "value": "1234567ABC000",
      "type": "string"
    },
    {
      "key": "buyer_tax_id",
      "value": "1234567RAM000",
      "type": "string"
    },
    {
      "key": "seller_name",
      "value": "Ma Société SARL",
      "type": "string"
    },
    {
      "key": "buyer_name",
      "value": "Mon Client SARL",
      "type": "string"
    },
    {
      "key": "seller_address_desc",
      "value": "Siège",
      "type": "string"
    },
    {
      "key": "seller_street",
      "value": "Avenue Habib Bourguiba",
      "type": "string"
    },
    {
      "key": "seller_city",
      "value": "Tunis",
      "type": "string"
    },
    {
      "key": "seller_postal_code",
      "value": "1000",
      "type": "string"
    },
    {
      "key": "buyer_address_desc",
      "value": "Siège",
      "type": "string"
    },
    {
      "key": "buyer_street",
      "value": "Rue de Marseille",
      "type": "string"
    },
    {
      "key": "buyer_city",
      "value": "Sfax",
      "type": "string"
    },
    {
      "key": "buyer_postal_code",
      "value": "3000",
      "type": "string"
    },
    {
      "key": "invoice_number",
      "value": "FACT-2026-000001",
      "type": "string"
    },
    {
      "key": "invoice_date_ddMMyy",
      "value": "150726",
      "type": "string"
    },
    {
      "key": "line1_item_code",
      "value": "ART-001",
      "type": "string"
    },
    {
      "key": "line1_description",
      "value": "Mon article",
      "type": "string"
    },
    {
      "key": "line1_qty",
      "value": "2",
      "type": "string"
    },
    {
      "key": "line1_ht",
      "value": "1000.000",
      "type": "string"
    },
    {
      "key": "total_ht",
      "value": "1000.000",
      "type": "string"
    },
    {
      "key": "total_tva",
      "value": "190.000",
      "type": "string"
    },
    {
      "key": "total_taxes",
      "value": "195.000",
      "type": "string"
    },
    {
      "key": "total_ttc",
      "value": "1195.000",
      "type": "string"
    },
    {
      "key": "payment_condition_code",
      "value": "I-122",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "🔐 Authentification",
      "item": [
        {
          "name": "Obtenir un token d'accès",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const json = pm.response.json();",
                  "if (json.access_token) {",
                  "  pm.collectionVariables.set('access_token', json.access_token);",
                  "  console.log(\"✅ access_token sauvegardé, expire dans\" + json.expires_in + 's');",
                  "} else {",
                  "  console.error(\"❌ Pas de access_token :\", JSON.stringify(json));",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/x-www-form-urlencoded"
              }
            ],
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                {
                  "key": "grant_type",
                  "value": "client_credentials"
                },
                {
                  "key": "client_id",
                  "value": "{{client_id}}"
                },
                {
                  "key": "client_secret",
                  "value": "{{client_secret}}"
                }
              ]
            },
            "url": {
              "raw": "{{base_url}}/oauth/token",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "oauth",
                "token"
              ]
            },
            "description": "Votre clé API est déjà liée à votre organisation — aucun `org_id` n'est requis. Le script de test sauvegarde automatiquement le token dans `{{access_token}}`."
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/oauth/token",
                  "host": [
                    "{{base_url}}/oauth/token"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"access_token\": \"eyJhbGciOiJIUzI1NiJ9....\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 3600,\n  \"scope\": \"invoice:write invoice:read ttn:submit\"\n}"
            },
            {
              "name": "401 Unauthorized",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/oauth/token",
                  "host": [
                    "{{base_url}}/oauth/token"
                  ]
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": \"invalid_client\",\n  \"error_description\": \"Invalid client credentials.\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "📄 Factures — JSON TEIF",
      "item": [
        {
          "name": "Soumettre une facture (JSON)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 201 || pm.response.code === 200) {",
                  "  const json = pm.response.json();",
                  "  if (json.id) {",
                  "    pm.collectionVariables.set('invoice_id', json.id);",
                  "    console.log(\"✅ invoice_id sauvegardé :\", json.id);",
                  "  }",
                  "} else {",
                  "  console.error(\"❌ Facture non créée :\", pm.response.text());",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"version\": \"1.8.8\",\n  \"controlingAgency\": \"TTN\",\n  \"header\": {\n    \"MessageSenderIdentifier\": {\n      \"@type\": \"I-01\",\n      \"#text\": \"{{seller_tax_id}}\"\n    },\n    \"MessageRecieverIdentifier\": {\n      \"@type\": \"I-01\",\n      \"#text\": \"{{buyer_tax_id}}\"\n    }\n  },\n  \"body\": {\n    \"bgm\": {\n      \"documentIdentifier\": \"{{invoice_number}}\",\n      \"documentTypeCode\": \"I-11\",\n      \"documentType\": \"Facture\"\n    },\n    \"dtm\": {\n      \"dateText\": [\n        {\n          \"functionCode\": \"I-31\",\n          \"format\": \"ddMMyy\",\n          \"value\": \"{{invoice_date_ddMMyy}}\"\n        }\n      ]\n    },\n    \"partnerSection\": {\n      \"partnerDetails\": [\n        {\n          \"functionCode\": \"I-62\",\n          \"nad\": {\n            \"partnerIdentifier\": {\n              \"type\": \"I-01\",\n              \"value\": \"{{seller_tax_id}}\"\n            },\n            \"partnerName\": {\n              \"nameType\": \"Qualification\",\n              \"value\": \"{{seller_name}}\"\n            },\n            \"partnerAdresses\": [\n              {\n                \"adressDescription\": \"Siège social\",\n                \"street\": \"{{seller_street}}\",\n                \"cityName\": \"{{seller_city}}\",\n                \"postalCode\": \"{{seller_postal_code}}\",\n                \"country\": {\n                  \"codeList\": \"ISO_3166-1\",\n                  \"value\": \"TN\"\n                }\n              }\n            ]\n          },\n          \"ctaSection\": [],\n          \"rffSection\": [],\n          \"loc\": []\n        },\n        {\n          \"functionCode\": \"I-61\",\n          \"nad\": {\n            \"partnerIdentifier\": {\n              \"type\": \"I-01\",\n              \"value\": \"{{buyer_tax_id}}\"\n            },\n            \"partnerName\": {\n              \"nameType\": \"Qualification\",\n              \"value\": \"{{buyer_name}}\"\n            },\n            \"partnerAdresses\": [\n              {\n                \"adressDescription\": \"Siège social\",\n                \"street\": \"{{buyer_street}}\",\n                \"cityName\": \"{{buyer_city}}\",\n                \"postalCode\": \"{{buyer_postal_code}}\",\n                \"country\": {\n                  \"codeList\": \"ISO_3166-1\",\n                  \"value\": \"TN\"\n                }\n              }\n            ]\n          },\n          \"ctaSection\": [],\n          \"rffSection\": [],\n          \"loc\": []\n        }\n      ]\n    },\n    \"linSection\": {\n      \"lin\": [\n        {\n          \"itemIdentifier\": \"1\",\n          \"linImd\": {\n            \"lang\": \"fr\",\n            \"itemCode\": \"{{line1_item_code}}\",\n            \"itemDescription\": \"{{line1_description}}\"\n          },\n          \"linQty\": {\n            \"quantity\": {\n              \"measurementUnit\": \"PCE\",\n              \"value\": \"{{line1_qty}}\"\n            }\n          },\n          \"linTax\": {\n            \"taxTypeName\": {\n              \"code\": \"I-1602\",\n              \"value\": \"TVA\"\n            },\n            \"taxDetails\": {\n              \"taxRate\": \"19\",\n              \"taxRateBasis\": \"Percentage\"\n            }\n          },\n          \"linMoa\": {\n            \"moaDetails\": [\n              {\n                \"moa\": {\n                  \"amountTypeCode\": \"I-188\",\n                  \"currencyCodeList\": \"ISO_4217\",\n                  \"amount\": {\n                    \"currencyIdentifier\": \"TND\",\n                    \"value\": \"{{line1_ht}}\"\n                  }\n                }\n              }\n            ]\n          },\n          \"subLin\": []\n        }\n      ]\n    },\n    \"invoiceTax\": {\n      \"invoiceTaxDetails\": [\n        {\n          \"tax\": {\n            \"taxTypeName\": {\n              \"code\": \"I-1602\",\n              \"value\": \"TVA\"\n            },\n            \"taxCategory\": \"I-1602\",\n            \"taxDetails\": {\n              \"taxRate\": \"19\",\n              \"taxRateBasis\": \"Percentage\"\n            }\n          },\n          \"amountDetails\": [\n            {\n              \"moa\": {\n                \"amountTypeCode\": \"I-177\",\n                \"currencyCodeList\": \"ISO_4217\",\n                \"amount\": {\n                  \"currencyIdentifier\": \"TND\",\n                  \"value\": \"{{total_ht}}\"\n                }\n              }\n            },\n            {\n              \"moa\": {\n                \"amountTypeCode\": \"I-178\",\n                \"currencyCodeList\": \"ISO_4217\",\n                \"amount\": {\n                  \"currencyIdentifier\": \"TND\",\n                  \"value\": \"{{total_tva}}\"\n                }\n              }\n            }\n          ]\n        }\n      ]\n    },\n    \"invoiceMoa\": {\n      \"amountDetails\": [\n        {\n          \"moa\": {\n            \"amountTypeCode\": \"I-172\",\n            \"currencyCodeList\": \"ISO_4217\",\n            \"amount\": {\n              \"currencyIdentifier\": \"TND\",\n              \"value\": \"{{total_ht}}\"\n            }\n          }\n        },\n        {\n          \"moa\": {\n            \"amountTypeCode\": \"I-181\",\n            \"currencyCodeList\": \"ISO_4217\",\n            \"amount\": {\n              \"currencyIdentifier\": \"TND\",\n              \"value\": \"{{total_taxes}}\"\n            }\n          }\n        },\n        {\n          \"moa\": {\n            \"amountTypeCode\": \"I-180\",\n            \"currencyCodeList\": \"ISO_4217\",\n            \"amount\": {\n              \"currencyIdentifier\": \"TND\",\n              \"value\": \"{{total_ttc}}\"\n            }\n          }\n        },\n        {\n          \"moa\": {\n            \"amountTypeCode\": \"I-177\",\n            \"currencyCodeList\": \"ISO_4217\",\n            \"amount\": {\n              \"currencyIdentifier\": \"TND\",\n              \"value\": \"{{total_ht}}\"\n            }\n          }\n        },\n        {\n          \"moa\": {\n            \"amountTypeCode\": \"I-176\",\n            \"currencyCodeList\": \"ISO_4217\",\n            \"amount\": {\n              \"currencyIdentifier\": \"TND\",\n              \"value\": \"{{total_ht}}\"\n            }\n          }\n        }\n      ]\n    },\n    \"pyt\": {\n      \"pytSectionDetails\": [\n        {\n          \"pytPai\": {\n            \"paiConditionCode\": \"{{payment_condition_code}}\",\n            \"paiMeansCode\": \"42\"\n          }\n        }\n      ]\n    }\n  },\n  \"additionnalDocuments\": null,\n  \"refTtnVal\": null,\n  \"signatures\": []\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/submit",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "submit"
              ]
            },
            "description": "Scope requis : `invoice:write`."
          },
          "response": [
            {
              "name": "201 Created",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/submit",
                  "host": [
                    "{{base_url}}/api/v2/invoices/submit"
                  ]
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n  \"invoiceNumber\": \"{{invoice_number}}\",\n  \"status\": \"VALIDATED\",\n  \"direction\": \"SENT\"\n}"
            }
          ]
        },
        {
          "name": "Lister les factures",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/invoices?page=0&pageSize=20&direction=SENT",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices"
              ],
              "query": [
                {
                  "key": "page",
                  "value": "0"
                },
                {
                  "key": "pageSize",
                  "value": "20"
                },
                {
                  "key": "direction",
                  "value": "SENT"
                }
              ]
            },
            "description": "Scope requis : `invoice:read`."
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices",
                  "host": [
                    "{{base_url}}/api/v2/invoices"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"content\": [\n    {\n      \"id\": \"{{invoice_id}}\",\n      \"invoiceNumber\": \"{{invoice_number}}\",\n      \"status\": \"ACCEPTED_TTN\"\n    }\n  ],\n  \"totalElements\": 1\n}"
            }
          ]
        },
        {
          "name": "Détail d'une facture",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "{{invoice_id}}"
              ]
            },
            "description": "Renvoie `invoice`, `teifJson`, `teifXml` et `ttnAcknowledgments`. Scope requis : `invoice:read`."
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}",
                  "host": [
                    "{{base_url}}/api/v2/invoices/{{invoice_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"invoice\": {\n    \"id\": \"{{invoice_id}}\",\n    \"status\": \"ACCEPTED_TTN\"\n  },\n  \"teifJson\": \"{...}\",\n  \"teifXml\": \"<TEIF>...</TEIF>\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "📄 Factures — XML TEIF",
      "item": [
        {
          "name": "Soumettre une facture (XML)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 201 || pm.response.code === 200) {",
                  "  const json = pm.response.json();",
                  "  if (json.id) {",
                  "    pm.collectionVariables.set('invoice_id', json.id);",
                  "    console.log(\"✅ invoice_id sauvegardé :\", json.id);",
                  "  }",
                  "} else {",
                  "  console.error(\"❌ Facture non créée :\", pm.response.text());",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/xml"
              },
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<TEIF controlingAgency=\"TTN\" version=\"1.8.8\">\n  <InvoiceHeader>\n    <MessageSenderIdentifier type=\"I-01\">{{seller_tax_id}}</MessageSenderIdentifier>\n    <MessageRecieverIdentifier type=\"I-01\">{{buyer_tax_id}}</MessageRecieverIdentifier>\n  </InvoiceHeader>\n  <InvoiceBody>\n    <Bgm>\n      <DocumentIdentifier>{{invoice_number}}</DocumentIdentifier>\n      <DocumentType code=\"I-11\">Facture</DocumentType>\n    </Bgm>\n    <Dtm>\n      <DateText format=\"ddMMyy\" functionCode=\"I-31\">{{invoice_date_ddMMyy}}</DateText>\n    </Dtm>\n    <PartnerSection>\n      <PartnerDetails functionCode=\"I-62\">\n        <Nad>\n          <PartnerIdentifier type=\"I-01\">{{seller_tax_id}}</PartnerIdentifier>\n          <PartnerName nameType=\"Qualification\">{{seller_name}}</PartnerName>\n          <PartnerAdresses lang=\"fr\">\n            <AdressDescription>{{seller_address_desc}}</AdressDescription>\n            <Street>{{seller_street}}</Street>\n            <CityName>{{seller_city}}</CityName>\n            <PostalCode>{{seller_postal_code}}</PostalCode>\n            <Country codeList=\"ISO_3166-1\">TN</Country>\n          </PartnerAdresses>\n        </Nad>\n      </PartnerDetails>\n      <PartnerDetails functionCode=\"I-61\">\n        <Nad>\n          <PartnerIdentifier type=\"I-01\">{{buyer_tax_id}}</PartnerIdentifier>\n          <PartnerName nameType=\"Qualification\">{{buyer_name}}</PartnerName>\n          <PartnerAdresses lang=\"fr\">\n            <AdressDescription>{{buyer_address_desc}}</AdressDescription>\n            <Street>{{buyer_street}}</Street>\n            <CityName>{{buyer_city}}</CityName>\n            <PostalCode>{{buyer_postal_code}}</PostalCode>\n            <Country codeList=\"ISO_3166-1\">TN</Country>\n          </PartnerAdresses>\n        </Nad>\n      </PartnerDetails>\n    </PartnerSection>\n    <LinSection>\n      <Lin>\n        <ItemIdentifier>1</ItemIdentifier>\n        <LinImd lang=\"fr\">\n          <ItemCode>{{line1_item_code}}</ItemCode>\n          <ItemDescription>{{line1_description}}</ItemDescription>\n        </LinImd>\n        <LinQty><Quantity measurementUnit=\"PCE\">{{line1_qty}}</Quantity></LinQty>\n        <LinTax>\n          <TaxTypeName code=\"I-1602\">TVA</TaxTypeName>\n          <TaxDetails><TaxRate>19</TaxRate></TaxDetails>\n        </LinTax>\n        <LinMoa>\n          <MoaDetails>\n            <Moa amountTypeCode=\"I-188\" currencyCodeList=\"ISO_4217\">\n              <Amount currencyIdentifier=\"TND\">{{line1_ht}}</Amount>\n            </Moa>\n          </MoaDetails>\n        </LinMoa>\n      </Lin>\n    </LinSection>\n    <InvoiceMoa>\n      <AmountDetails>\n        <Moa amountTypeCode=\"I-172\" currencyCodeList=\"ISO_4217\"><Amount currencyIdentifier=\"TND\">{{total_ht}}</Amount></Moa>\n      </AmountDetails>\n      <AmountDetails>\n        <Moa amountTypeCode=\"I-181\" currencyCodeList=\"ISO_4217\"><Amount currencyIdentifier=\"TND\">{{total_taxes}}</Amount></Moa>\n      </AmountDetails>\n      <AmountDetails>\n        <Moa amountTypeCode=\"I-180\" currencyCodeList=\"ISO_4217\"><Amount currencyIdentifier=\"TND\">{{total_ttc}}</Amount></Moa>\n      </AmountDetails>\n    </InvoiceMoa>\n    <InvoiceTax>\n      <InvoiceTaxDetails>\n        <Tax>\n          <TaxTypeName code=\"I-1602\">TVA</TaxTypeName>\n          <TaxDetails><TaxRate>19</TaxRate></TaxDetails>\n        </Tax>\n        <AmountDetails>\n          <Moa amountTypeCode=\"I-178\" currencyCodeList=\"ISO_4217\"><Amount currencyIdentifier=\"TND\">{{total_tva}}</Amount></Moa>\n        </AmountDetails>\n      </InvoiceTaxDetails>\n    </InvoiceTax>\n  </InvoiceBody>\n</TEIF>",
              "options": {
                "raw": {
                  "language": "xml"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/submit-xml",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "submit-xml"
              ]
            },
            "description": "Alternative au format JSON si votre système génère déjà du XML TEIF. Scope requis : `invoice:write`."
          },
          "response": [
            {
              "name": "201 Created",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/submit-xml",
                  "host": [
                    "{{base_url}}/api/v2/invoices/submit-xml"
                  ]
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n  \"invoiceNumber\": \"{{invoice_number}}\",\n  \"status\": \"VALIDATED\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "✅ Validation TEIF",
      "item": [
        {
          "name": "Valider un XML (XSD uniquement)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"xml\": \"<TEIF controlingAgency=\\\"TTN\\\" version=\\\"1.8.8\\\">...</TEIF>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/api/v2/teif/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "teif",
                "validate"
              ]
            },
            "description": "Valide un XML TEIF contre le schéma XSD sans créer de facture. Champ du corps : `xml`. Scope requis : `invoice:read` ou `invoice:write`."
          },
          "response": [
            {
              "name": "200 OK — valid",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/teif/validate",
                  "host": [
                    "{{base_url}}/api/v2/teif/validate"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"valid\": true,\n  \"issues\": []\n}"
            },
            {
              "name": "200 OK — invalid",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/teif/validate",
                  "host": [
                    "{{base_url}}/api/v2/teif/validate"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"valid\": false,\n  \"issues\": [\n    {\n      \"type\": \"XML_SCHEMA_VIOLATION\",\n      \"severity\": \"ERROR\",\n      \"message\": \"...\"\n    }\n  ]\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "✍️ Signature et envoi TTN",
      "item": [
        {
          "name": "Signer une facture (SEAL)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"provider\": \"seal\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/sign",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "{{invoice_id}}",
                "sign"
              ]
            },
            "description": "Signer une facture au statut VALIDATED. Scope requis : `seal:sign` (SEAL Max) ou `digigo:sign` (DigiGO, avec `{\"provider\":\"digigo\"}`). Ne soumet pas à TTN — utilisez ensuite `submit-ttn`, ou préférez `sign-and-send` ci-dessous pour tout faire en un appel."
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/sign",
                  "host": [
                    "{{base_url}}/api/v2/invoices/{{invoice_id}}/sign"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"{{invoice_id}}\",\n  \"status\": \"SIGNED\",\n  \"signedAt\": \"2026-07-12T10:00:00Z\"\n}"
            }
          ]
        },
        {
          "name": "Envoyer une facture signée à TTN",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/submit-ttn",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "{{invoice_id}}",
                "submit-ttn"
              ]
            },
            "description": "Soumet une facture déjà signée à TTN (Tunisia Trade Net). Scope requis : `ttn:submit`. Consomme le quota de signature mensuel (sauf si déjà comptabilisé par un job sign-and-send)."
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/submit-ttn",
                  "host": [
                    "{{base_url}}/api/v2/invoices/{{invoice_id}}/submit-ttn"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"{{invoice_id}}\",\n  \"status\": \"ACCEPTED_TTN\",\n  \"ttnGeneratedRef\": \"TTN-REF-000123\"\n}"
            }
          ]
        },
        {
          "name": "Signer + envoyer à TTN (recommandé, async)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const json = pm.response.json();",
                  "if (json.jobId) {",
                  "  pm.collectionVariables.set('job_id', json.jobId);",
                  "  console.log(\"✅ job_id sauvegardé :\", json.jobId);",
                  "} else {",
                  "  console.error(\"❌ Pas de jobId :\", JSON.stringify(json));",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"signatureType\": \"SEAL\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/sign-and-send",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "{{invoice_id}}",
                "sign-and-send"
              ]
            },
            "description": "Met en file d'attente la signature et l'envoi à TTN en une seule opération asynchrone. `signatureType` : `SEAL` ou `DIGIGO` selon votre plan. Le script de test sauvegarde le `jobId` retourné dans `{{job_id}}`."
          },
          "response": [
            {
              "name": "200 OK — job créé",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/sign-and-send",
                  "host": [
                    "{{base_url}}/api/v2/invoices/{{invoice_id}}/sign-and-send"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"jobId\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n  \"invoiceId\": \"{{invoice_id}}\",\n  \"jobType\": \"SIGN_AND_SUBMIT_SEAL\",\n  \"status\": \"PENDING\",\n  \"success\": true\n}"
            },
            {
              "name": "402 Payment Required — quota épuisé",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/sign-and-send",
                  "host": [
                    "{{base_url}}/api/v2/invoices/{{invoice_id}}/sign-and-send"
                  ]
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": \"NO_SIGNATURE_CREDITS\",\n  \"message\": \"No signing quota or signature-pack credits available.\",\n  \"packsRemaining\": 0\n}"
            }
          ]
        },
        {
          "name": "Suivre le job (poll)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/jobs/{{job_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "jobs",
                "{{job_id}}"
              ]
            },
            "description": "`status` passe de `PENDING` à `COMPLETED` ou `FAILED`. Scope requis : `invoice:read`."
          },
          "response": [
            {
              "name": "200 OK — completed",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/jobs/{{job_id}}",
                  "host": [
                    "{{base_url}}/api/v2/jobs/{{job_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"jobId\": \"{{job_id}}\",\n  \"invoiceId\": \"{{invoice_id}}\",\n  \"status\": \"COMPLETED\",\n  \"progress\": 100,\n  \"ttnFinalResult\": {\n    \"status\": \"ACCEPTED_TTN\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "📎 Artefacts (XML / PDF)",
      "item": [
        {
          "name": "Télécharger le PDF",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/pdf",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "{{invoice_id}}",
                "pdf"
              ],
              "query": [
                {
                  "key": "pdfTemplate",
                  "value": "",
                  "description": "Optionnel — sinon le modèle par défaut de l'organisation est utilisé",
                  "disabled": true
                },
                {
                  "key": "lang",
                  "value": "",
                  "description": "Optionnel — langue du document (fr/en/ar)",
                  "disabled": true
                }
              ]
            },
            "description": "Réponse binaire (`application/pdf`), quel que soit le statut de la facture (brouillon inclus). Scope requis : `invoice:read`."
          },
          "response": []
        },
        {
          "name": "Récupérer le XML généré",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/generated-xml",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "{{invoice_id}}",
                "generated-xml"
              ]
            },
            "description": "⚠️ Au-delà du statut SIGNED, cet endpoint régénère un XML NON SIGNÉ à la volée (perd la signature et le QR code TTN). Pour l'artefact final réellement signé/horodaté TTN, lisez plutôt le champ `teifXml` de `GET /invoices/:id`. Scope requis : `invoice:read`."
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/{{invoice_id}}/generated-xml",
                  "host": [
                    "{{base_url}}/api/v2/invoices/{{invoice_id}}/generated-xml"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"note\": \"raw application/xml body, not JSON\"\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "📊 Consultation et statistiques",
      "item": [
        {
          "name": "Statistiques du tableau de bord",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/stats",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "stats"
              ]
            }
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/stats",
                  "host": [
                    "{{base_url}}/api/v2/invoices/stats"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"totalCount\": 42,\n  \"sentCount\": 40,\n  \"errorCount\": 1,\n  \"totalRevenue\": 12500.5,\n  \"byMonth\": [\n    {\n      \"month\": \"2026-07\",\n      \"created\": 12,\n      \"sent\": 11,\n      \"errors\": 0\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "Statistiques par clé API",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/invoices/api-key-stats",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "invoices",
                "api-key-stats"
              ]
            }
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/invoices/api-key-stats",
                  "host": [
                    "{{base_url}}/api/v2/invoices/api-key-stats"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"organizationId\": \"org_xxxx\",\n  \"totalInvoices\": 42,\n  \"stats\": [\n    {\n      \"appId\": \"{{client_id}}\",\n      \"invoicesCreated\": 42,\n      \"invoicesSigned\": 40,\n      \"invoicesSubmittedToTtn\": 38\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "Mon organisation (identité, plan, stats)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/organization",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "organization"
              ]
            },
            "description": "Retourne votre organisation : identité (dont taxIdentifier — doit correspondre au MessageSenderIdentifier de vos factures TEIF), plan/abonnement, crédits de signature restants, et les mêmes statistiques que /invoices/stats et /invoices/api-key-stats."
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/organization",
                  "host": [
                    "{{base_url}}/api/v2/organization"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"orgId\": \"5b1e2b7a-4c31-4e2a-9d9a-7b0f9e6a1234\",\n  \"orgName\": \"Société ABC SARL\",\n  \"taxIdentifier\": \"1234567ABCD000\",\n  \"status\": \"active\",\n  \"isTestAccount\": false,\n  \"isSandboxAccount\": false,\n  \"partnerStatus\": null,\n  \"createdAt\": \"2026-01-10T09:12:00.000Z\",\n  \"plan\": {\n    \"slug\": \"digigo-business\",\n    \"name\": \"DigiGO Business\",\n    \"status\": \"active\",\n    \"monthlyLimit\": 500,\n    \"isUnlimited\": false,\n    \"currentPeriodStart\": \"2026-07-01T00:00:00.000Z\",\n    \"currentPeriodEnd\": \"2026-07-31T23:59:59.000Z\",\n    \"trialEndsAt\": null\n  },\n  \"signatureCredits\": {\n    \"remainingTotal\": 32,\n    \"nearestExpiryAt\": \"2027-01-15T00:00:00.000Z\"\n  },\n  \"stats\": {\n    \"totalCount\": 128,\n    \"sentCount\": 120,\n    \"errorCount\": 3,\n    \"totalRevenue\": 45210.5,\n    \"byMonth\": [\n      {\n        \"month\": \"2026-07\",\n        \"created\": 12,\n        \"sent\": 11,\n        \"errors\": 0\n      }\n    ]\n  },\n  \"apiKeyStats\": {\n    \"organizationId\": \"5b1e2b7a-4c31-4e2a-9d9a-7b0f9e6a1234\",\n    \"totalInvoices\": 128,\n    \"stats\": [\n      {\n        \"appId\": \"{{client_id}}\",\n        \"invoicesCreated\": 128,\n        \"invoicesSigned\": 120,\n        \"invoicesSubmittedToTtn\": 118\n      }\n    ]\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "🔔 Webhooks",
      "item": [
        {
          "name": "Créer un webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://votre-erp.example.com/webhooks/fatoora\",\n  \"events\": [\n    \"invoice.validated\",\n    \"invoice.signed\",\n    \"invoice.accepted_ttn\",\n    \"invoice.rejected_ttn\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/api/v2/webhooks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "webhooks"
              ]
            },
            "description": "Le secret du webhook est retourné une seule fois — sauvegardez-le pour vérifier la signature des événements reçus."
          },
          "response": [
            {
              "name": "201 Created",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/webhooks",
                  "host": [
                    "{{base_url}}/api/v2/webhooks"
                  ]
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"wh_xxxx\",\n  \"url\": \"https://votre-erp.example.com/webhooks/fatoora\",\n  \"secret\": \"whsec_xxxxxxxxxxxx\"\n}"
            }
          ]
        },
        {
          "name": "Lister les webhooks",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/webhooks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "webhooks"
              ]
            }
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/webhooks",
                  "host": [
                    "{{base_url}}/api/v2/webhooks"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"webhooks\": [\n    {\n      \"id\": \"wh_xxxx\",\n      \"url\": \"https://votre-erp.example.com/webhooks/fatoora\",\n      \"isActive\": true\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "Tester un webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v2/webhooks/wh_xxxx/test",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v2",
                "webhooks",
                "wh_xxxx",
                "test"
              ]
            }
          },
          "response": [
            {
              "name": "200 OK",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/v2/webhooks/wh_xxxx/test",
                  "host": [
                    "{{base_url}}/api/v2/webhooks/wh_xxxx/test"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"delivered\": true\n}"
            }
          ]
        }
      ]
    }
  ]
}
