FEL certifier registry
FlowPOS separates SAT reference data, merchant configuration, and document certification results. The billing screen certifier dropdown is not a full dump of the database table—it lists only certifiers FlowPOS can certify against today.
Three layers
| Layer | Storage | Purpose |
|---|---|---|
| Registry | fel_certifier | Official SAT certifier slug, legal name, and NIT per country |
| Merchant config | business.fel_certifier_config JSONB | Selected slug + encrypted credentials |
| Document result | sale, order_bill, credit_note, debit_note | Certifier name/NIT returned at certification time |
There is no foreign key from business to fel_certifier. The slug in felCertifierConfig.felCertifier is validated against both the integrated allowlist and the registry at save time.
Registry vs integrated (why the dropdown shows one option)
Guatemala has many SAT-authorized FEL certifiers. The migration seeds all of them into fel_certifier for reference (legal names, NITs, receipts). FlowPOS only integrates with certifiers that have a wired API adapter and production URL.
flowchart LR
DB["fel_certifier\n~18 SAT rows"]
API["GET /fel/certifiers"]
Allow["FEL_INTEGRATED_CERTIFIER_SLUGS"]
PWA["FelCredentialsSection\nfilter isIntegrated"]
Select["Billing dropdown"]
DB --> API
Allow --> API
API -->|"isIntegrated flag"| PWA --> Select
| Question | Answer |
|---|---|
Why does SELECT * FROM fel_certifier return many rows? | The table is the full SAT registry for display and print normalization. |
| Why does the PWA dropdown show one certifier? | The UI filters to isIntegrated === true. Only integrated slugs are selectable. |
| What happens if I pick a non-integrated slug via API? | PATCH /businesses/:id/bill rejects it: "FEL certifier '…' is not integrated for certification yet". |
Integrated allowlist (source of truth)
File: packages/global/consts/fel-integrated-certifiers.const.ts
Currently integrated:
| Slug | Legal name (registry) | API URL configured |
|---|---|---|
digifact | DIGIFACT SERVICIOS, S. A. | Yes (GuatemalanCertifiersUrls) |
Not integrated yet (examples):
| Slug / case | Reason |
|---|---|
infile | Enum exists for legacy configs; excluded from allowlist until a real Infile URL is set in certifiers-urls.const.ts. |
| All other registry rows (Innova, Megaprint, Tekra, …) | Row exists in fel_certifier only; no provider adapter or URL in FlowPOS yet. |
Backend sets isIntegrated per row:
isIntegrated: isFelIntegratedCertifierSlug(row.name)
PWA billing (FelCredentialsSection) loads the API and filters client-side:
const rows = await listFelCertifiers(token!, countryId);
return rows.filter((row) => row.isIntegrated);
Merchant-facing explanation: FEL setup — certifier selection.
API
List certifiers
GET /fel/certifiers?countryId=GT
Returns every registry row for the country, each with isIntegrated: true | false. Example shape:
{
"id": "56730a25-9ced-43df-8de9-7924af1558f9",
"name": "digifact",
"legalName": "DIGIFACT SERVICIOS, S. A.",
"taxId": "77454820",
"countryId": "GT",
"isIntegrated": true
}
The billing screen uses integrated rows only. Other consumers (admin tools, future UI) may show the full list.
Save billing config
PATCH /businesses/:id/bill validates felCertifier via FelCertifierService.validateIntegratedSlug (allowlist + registry row must exist).
Print and certification fallback
Backend code resolves display fields with resolveFelCertifierDisplayFields:
- When the merchant's certifier slug maps to a
fel_certifierrow, use the registry legal name (official SAT name, e.g.DIGIFACT SERVICIOS, S. A.) - Use the certified NIT from the API when present, otherwise the registry NIT
- When no registry row is available, fall back to persisted API/document values
Certifier APIs sometimes return verbose spellings (e.g. DIGIFACT SERVICIOS, SOCIDAD ANONIMA); receipts and new certifications use the registry name instead.
This applies to sales (event handler), restaurant bills, credit/debit notes, and document-print payloads.
Adding a new integrated certifier
- Seed or verify the row in
fel_certifier(migration or manual insert). - Add the provider adapter and URL in the backend FEL module (
ProviderService,GuatemalanCertifiersUrls, infrastructure adapter). - Add the slug to
FEL_INTEGRATED_CERTIFIER_SLUGSinfel-integrated-certifiers.const.ts. - Map the slug in
mapProviderNameToRpaFormatif using RPAfelApi. - Verify the billing dropdown shows the new option and bill-save succeeds in staging.
See also: FEL Provider Port.
Related docs
- FEL setup (merchant) — billing screen and certifier dropdown
- FEL Module Architecture — certification orchestration
- FEL Provider Port — adding provider adapters
- Retail sales FEL workflow
- Restaurant FEL workflow