Issuers, establishments and emission points
An issuer is a taxpayer (RUC) that issues documents. An account can have several issuers. Each issuer has establishments (three-digit codes such as 001, as registered in the RUC) and each establishment has emission points (001, 002, …). Together with the sequential they form the document number: 001-001-000000123.
Managing issuers, establishments and emission points through the API needs an account-scoped read_write key, also to read them. The console manages the same resources under Issuers, where an issuer is only added from its certificate (New issuer).
| Operation | Endpoint |
|---|---|
Create an issuer from its .p12 certificate |
POST /v1/issuer-onboardings, GET /v1/issuer-onboardings/{onboardingId}, POST .../{onboardingId}/complete |
| Create, list issuers | POST, GET /v1/issuers |
| Read, update, delete an issuer | GET, PATCH, DELETE /v1/issuers/{issuerId} |
| Create, list establishments | POST, GET /v1/issuers/{issuerId}/establishments |
| Read, update, delete an establishment | GET, PATCH, DELETE /v1/issuers/{issuerId}/establishments/{establishmentId} |
| Create, list emission points | POST, GET .../establishments/{establishmentId}/emission-points |
| Read, delete an emission point | GET, DELETE .../emission-points/{emissionPointId} |
Create an issuer from its certificate
Section titled “Create an issuer from its certificate”The shortest way to add an issuer is to upload only its electronic signature (.p12) and its password. Flashpi verifies the certificate, reads the RUC and the holder from it, proposes the RUC and the legal name for you to review and complete the tax profile and, on completion, creates the issuer with its establishment 001 and its emission point 001. The same certificate serves test and live, so there is no need to upload it twice. The console does these steps under Issuers, New issuer.
It works with an account-scoped read_write key of either environment.
1. Upload the certificate
Section titled “1. Upload the certificate”curl https://api.flashpi.com.ec/v1/issuer-onboardings \ -H "Authorization: Bearer $FLASHPI_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -F "file=@signature.p12" \ -F "password=$P12_PASSWORD"The file and the password have the same limits as a certificate upload and are encrypted as soon as they arrive; the Idempotency-Key fingerprint leaves the password out. The answer is 202 Accepted, with the onboarding’s Location header, starting in verifying:
{ "id": "01a0fd70-2b4c-7d1e-9f3a-5c6b7d8e9f01", "status": "verifying", "expiresAt": "2026-10-08T16:20:31.000Z", "rejection": null, "certificate": null, "proposedRuc": null, "rucNeedsConfirmation": false, "existingIssuer": null, "sri": null, "prefill": null, "completed": null, "createdAt": "2026-10-02T16:20:31.000Z", "updatedAt": "2026-10-02T16:20:31.000Z"}2. Poll the onboarding until it is ready
Section titled “2. Poll the onboarding until it is ready”curl https://api.flashpi.com.ec/v1/issuer-onboardings/01a0fd70-2b4c-7d1e-9f3a-5c6b7d8e9f01 \ -H "Authorization: Bearer $FLASHPI_API_KEY"Read it again every few seconds while its status is verifying (verification usually takes under a minute):
status |
Meaning |
|---|---|
verifying |
Flashpi checks the password, the signing key, the validity, the chain and the revocation, as in a certificate’s verification. |
ready |
The certificate is valid: the onboarding carries its details and can be completed. |
rejected |
rejection.code and rejection.message say why, with the same codes as a rejected certificate. Fix the cause and start another onboarding. |
completed |
It was already completed; completed has the issuer’s and the certificate’s IDs. |
expired |
It was not completed within 6 days and can no longer be completed; its encrypted upload is deleted automatically soon after (about 7 days after it was uploaded). Start another onboarding. |
Flashpi deletes an onboarding 30 days after it is completed, expires or is rejected; from then on GET /v1/issuer-onboardings/{onboardingId} answers 404 not_found. Keep the IDs from the complete response, or read the issuer with GET /v1/issuers/{issuerId}, instead of reading the onboarding again.
A ready onboarding of a company:
{ "id": "01a0fd70-2b4c-7d1e-9f3a-5c6b7d8e9f01", "status": "ready", "expiresAt": "2026-10-08T16:20:31.000Z", "rejection": null, "certificate": { "serialNumber": "4f2a9c01", "validFrom": "2026-09-30T15:00:00.000Z", "validTo": "2028-09-29T15:00:00.000Z", "issuingCa": { "code": "SECURITY_DATA", "displayName": "Security Data" }, "holder": { "commonName": "MARIA FERNANDA TORRES", "organization": "TOSTADURIA ANDINA S.A." }, "identification": { "ruc": "1790000000001", "rucSource": "certificate", "cedula": null } }, "proposedRuc": "1790000000001", "rucNeedsConfirmation": false, "existingIssuer": null, "sri": { "status": "disabled", "fetchedAt": null, "profile": null, "warnings": [] }, "prefill": { "ruc": "1790000000001", "legalName": "TOSTADURIA ANDINA S.A.", "tradeName": null, "headOfficeAddress": null, "taxProfile": { "keepsAccounting": null, "rimpeRegime": null, "specialTaxpayer": null, "withholdingAgent": null } }, "completed": null, "createdAt": "2026-10-02T16:20:31.000Z", "updatedAt": "2026-10-02T16:20:40.000Z"}| Field | Notes |
|---|---|
certificate |
Public details of the certificate, with no signing material: its serial number, validity, issuing authority, the holder (commonName) and their company (organization), and the identification it carries. |
proposedRuc, rucNeedsConfirmation |
The RUC the onboarding completes with. When it does not come from the certificate itself, rucNeedsConfirmation is true and you must confirm it (see A natural person’s RUC). proposedRuc is null when the certificate carries neither a RUC nor a cédula (see No RUC in the certificate). |
existingIssuer |
The issuer of your account that already has that RUC, if any: completing renews its certificate (see Renewal). |
sri |
The lookup in the SRI’s RUC registry, turned off today (status: "disabled"). See SRI data. |
prefill |
The values to start the profile from: the RUC and the legal name, which is a company certificate’s organization or a person’s commonName. The trade name, the head office address and the tax profile only come from the SRI, so today they are null and you type them. null where nothing is known. |
3. Complete the onboarding
Section titled “3. Complete the onboarding”Send the issuer with the same fields as Create an issuer, starting from prefill, correcting whatever needs it and filling in what is missing. You type the special taxpayer and withholding agent resolution numbers.
curl https://api.flashpi.com.ec/v1/issuer-onboardings/01a0fd70-2b4c-7d1e-9f3a-5c6b7d8e9f01/complete \ -H "Authorization: Bearer $FLASHPI_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "legalName": "TOSTADURIA ANDINA S.A.", "tradeName": "Café Andino", "headOfficeAddress": "Av. Amazonas N36-152 y Naciones Unidas, Quito", "taxProfile": { "keepsAccounting": true, "withholdingAgentResolution": "6498", "rimpeRegime": null } }'The answer is 201 Created with the issuer and its certificate, with the issuer’s Location header. The issuer already has establishment 001 at its head office address and emission point 001. The certificate serves test and live (allModes: true) and starts processing, like any certificate: read it under the issuer until it is accepted.
{ "issuer": { "id": "01a0fd6a-d098-76ca-b492-1bcb6505a7bd", "ruc": "1790000000001", "legalName": "TOSTADURIA ANDINA S.A.", "tradeName": "Café Andino", "headOfficeAddress": "Av. Amazonas N36-152 y Naciones Unidas, Quito", "taxProfile": { "keepsAccounting": true, "specialTaxpayerNumber": null, "withholdingAgentResolution": "6498", "rimpeRegime": null, "largeTaxpayerResolution": null }, "branding": { "brandColor": null }, "sendEmailByDefault": true, "createdAt": "2026-10-02T16:22:05.000Z", "updatedAt": "2026-10-02T16:22:05.000Z" }, "certificate": { "id": "01a0fd6e-f718-7c9c-b50c-fafb236eb1a6", "issuerId": "01a0fd6a-d098-76ca-b492-1bcb6505a7bd", "environment": "test", "allModes": true, "status": "processing", "usable": false, "subject": null, "issuedBy": null, "serialNumber": null, "validFrom": null, "validUntil": null, "sha256Fingerprint": null, "ruc": null, "revocation": null, "rejection": null, "createdAt": "2026-10-02T16:22:05.000Z", "updatedAt": "2026-10-02T16:22:05.000Z" }}| Error | When |
|---|---|
409 issuer_onboarding_not_ready |
The onboarding is still verifying. |
409 issuer_onboarding_rejected |
The certificate was rejected. |
409 issuer_onboarding_completed |
The onboarding was already completed. |
409 issuer_onboarding_expired |
6 days passed without completing it. |
409 issuer_already_exists |
Another request created an issuer with this RUC meanwhile. The onboarding is still ready: completing it again renews that issuer (see Renewal). |
422 validation_failed |
A field of a new issuer is missing, or the ruc is required or does not match the certificate (ruc_mismatch in errors). |
A natural person’s RUC
Section titled “A natural person’s RUC”A natural person’s certificate usually carries their cédula, not a RUC. Flashpi then proposes the cédula followed by 001 (identification.rucSource: "cedula", rucNeedsConfirmation: true), and completing must send the ruc: the proposed one, or another one whose first 10 digits are the cédula. Another RUC gets 422 with ruc_mismatch on the ruc field. For a certificate with the cédula 1700000001:
{ "ruc": "1700000001001", "legalName": "PEREZ LOPEZ JUAN CARLOS", "headOfficeAddress": "Av. Naciones Unidas E7-10, Quito", "taxProfile": { "keepsAccounting": false, "rimpeRegime": "entrepreneur" }}When the RUC comes from the certificate itself (rucSource: "certificate"), ruc can be left out; when sent, it must be that RUC.
No RUC in the certificate
Section titled “No RUC in the certificate”Some certificates carry neither a RUC nor a cédula that Flashpi can read. The ready onboarding then has proposedRuc: null, rucNeedsConfirmation: true and sri: null, since there was no RUC to ask the SRI about, and prefill only carries what the certificate says. Completing must send the ruc, 13 digits ending in 001 (422 with the ruc required otherwise). Flashpi cannot compare it with the certificate, so make sure it is the holder’s RUC. When your account already has an issuer with that RUC, completing renews its certificate and the ruc alone is enough; otherwise send the fields of a new issuer too.
Renewal
Section titled “Renewal”When your account already has an issuer with the certificate’s RUC, the onboarding carries existingIssuer and completing it renews that issuer’s certificate: no other issuer is created, and the body may be {}. The issuer’s profile does not change; update it with PATCH /v1/issuers/{issuerId} if needed. The new certificate serves test and live and takes over as soon as it is accepted (see Which certificate signs).
SRI data
Section titled “SRI data”Today Flashpi does not ask the SRI’s public RUC registry: sri.status is disabled and prefill only carries the RUC and the legal name read from the certificate. The tax information is your responsibility: review and fill in every value before completing the onboarding.
Once the lookup is turned on, Flashpi will ask once, after verifying the certificate, about the proposed RUC, and prefill will take the legal name, the trade name, the head office address and the tax profile from the SRI. sri will then carry what the SRI answered:
{ "sri": { "status": "found", "fetchedAt": "2026-10-02T16:20:40.000Z", "profile": { "legalName": "TOSTADURIA ANDINA S.A.", "tradeName": "CAFE ANDINO", "taxpayerStatus": "ACTIVO", "keepsAccounting": true, "specialTaxpayer": false, "withholdingAgent": true, "rimpeRegime": "general", "headOfficeAddress": "PICHINCHA / QUITO / IÑAQUITO / AV. AMAZONAS N36-152" }, "warnings": [] }}sri.statusisfound,not_found(the SRI has no such RUC: check that it is right),unavailable(the SRI did not answer) ordisabled(it was not asked).sriisnullwhen the certificate gave no RUC to ask about (see No RUC in the certificate). Without a profile,prefillonly carries what the certificate says and you fill in the rest.sri.warningssays when the RUC is notACTIVO(inactive), when the SRI flags the taxpayer as a ghost taxpayer (ghost) or for nonexistent transactions (nonexistent_transactions), or when its head office is listed as closed (head_office_closed). They are only warnings: they never stop the onboarding.profile.rimpeRegimeisentrepreneur,popular_business,general(not in RIMPE) orunknown(it could not be read: choose the regime yourself).generalis sent on completion asrimpeRegime: null, and the SRI only says whether the taxpayer is a special taxpayer or a withholding agent: you type the resolution numbers.
Create an issuer
Section titled “Create an issuer”You can also create an issuer with JSON, without uploading its certificate: it keeps working the same, and you upload the certificate separately afterwards (see Certificates). The console no longer offers this way.
curl https://api.flashpi.com.ec/v1/issuers \ -H "Authorization: Bearer $FLASHPI_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "ruc": "1790000000001", "legalName": "Tostaduría Andina S.A.", "tradeName": "Café Andino", "headOfficeAddress": "Av. Amazonas N36-152 y Naciones Unidas, Quito", "taxProfile": { "keepsAccounting": true, "withholdingAgentResolution": "6498" }, "branding": { "brandColor": "#5B3A29" }, "sendEmailByDefault": true }'The answer is 201 Created with the issuer:
{ "id": "01a0fd6a-d098-76ca-b492-1bcb6505a7bd", "ruc": "1790000000001", "legalName": "Tostaduría Andina S.A.", "tradeName": "Café Andino", "headOfficeAddress": "Av. Amazonas N36-152 y Naciones Unidas, Quito", "taxProfile": { "keepsAccounting": true, "specialTaxpayerNumber": null, "withholdingAgentResolution": "6498", "rimpeRegime": null, "largeTaxpayerResolution": null }, "branding": { "brandColor": "#5b3a29" }, "sendEmailByDefault": true, "createdAt": "2026-10-02T16:20:31.000Z", "updatedAt": "2026-10-02T16:20:31.000Z"}| Field | Notes |
|---|---|
ruc |
13 digits ending in 001. Only the format is checked: newer RUCs fail the old modulo-11 check digit, so Flashpi never verifies it. It cannot change later, and an account cannot register the same RUC twice (409 issuer_already_exists; with the onboarding from the certificate, the same RUC renews the issuer). |
legalName, tradeName |
The legal name (razón social) as registered in the RUC, and the optional trade name (nombre comercial). The email to the buyer shows the trade name, or the legal name, as the sender. |
headOfficeAddress |
The head office address (dirección matriz). |
taxProfile |
See Tax profile. |
branding.brandColor |
The brand color of the RIDE and the buyer email, #RRGGBB (returned in lowercase). |
sendEmailByDefault |
Whether authorized documents are emailed to the buyer when a request does not say (options.sendEmail). true by default. See RIDE and email. |
Tax profile
Section titled “Tax profile”The tax profile is configured once, on the issuer. Flashpi writes the matching tags and legends on every document, so requests never repeat them.
| Field | What Flashpi adds to the documents |
|---|---|
keepsAccounting (required) |
Whether the taxpayer must keep accounting (obligado a llevar contabilidad). |
specialTaxpayerNumber |
The special taxpayer (contribuyente especial) resolution number, 3 to 13 letters or digits. Withholding receipts accept at most 5 characters (incompatible_issuer_profile otherwise). |
withholdingAgentResolution |
The withholding agent (agente de retención) resolution number, digits only. |
rimpeRegime |
entrepreneur prints CONTRIBUYENTE RÉGIMEN RIMPE and popular_business prints CONTRIBUYENTE NEGOCIO POPULAR - RÉGIMEN RIMPE. null outside RIMPE. |
largeTaxpayerResolution |
The large taxpayer (gran contribuyente) resolution, printed as the Gran Contribuyente additional field. |
Flashpi also adds the RUC Proveedor additional field to every document: the RUC of the registered provider of electronic invoicing, Signia Digital S.A. (0993411372001). A document carries at most 15 additional fields, so these legends take one or two of them, and their names are reserved in your additionalInfo (reserved_name).
Establishments and emission points
Section titled “Establishments and emission points”curl https://api.flashpi.com.ec/v1/issuers/01a0fd6a-d098-76ca-b492-1bcb6505a7bd/establishments \ -H "Authorization: Bearer $FLASHPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "code": "001", "address": "Av. Amazonas N34-12, Quito" }'curl https://api.flashpi.com.ec/v1/issuers/01a0fd6a-d098-76ca-b492-1bcb6505a7bd/establishments/01a0fd6b-41e0-7c72-a0ce-848650c4f91d/emission-points \ -H "Authorization: Bearer $FLASHPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "code": "001" }'- An establishment has a three-digit
code, as registered in the RUC, and anaddressprinted on its documents. Only the address can change later (PATCH). - An emission point has a three-digit
codeand nothing else to change. - A code already used gets
409establishment_already_existsoremission_point_already_exists. - Lists of establishments and emission points are ordered by code; the list of issuers is newest first. See Pagination.
Documents name the establishment and the emission point by their codes ("establishment": "001"), not by their IDs.
Sequentials and access keys
Section titled “Sequentials and access keys”Flashpi assigns the next sequential atomically per issuer, establishment, emission point and document type, so concurrent requests never get the same number, and generates the 49-digit access key with a random numeric code. Invoices and credit notes of the same emission point have separate series.
A request may send its own sequential (1 to 999,999,999), for example to continue the numbering of the system you migrate from:
- It must not be used yet by a document of the same type and series (
409sequential_already_used). - When it is higher than the last one, later automatic sequentials continue after it. A lower free sequential fills a gap and leaves the counter alone.
- A series that reached 999,999,999 gets
409sequentials_exhausted. - The shared demo issuer never accepts one.
Update and delete
Section titled “Update and delete”PATCH /v1/issuers/{issuerId}changes the fields you send;nullclears an optional field. The RUC never changes.DELETE /v1/issuers/{issuerId}deletes the issuer with its establishments, emission points and issuer-scoped API keys. It is refused with409resource_in_usewhile documents or certificates reference it, so an issuer that issued documents stays.- An establishment or emission point with documents cannot be deleted either (
409resource_in_use).
Branding
Section titled “Branding”Today an issuer’s branding is its brandColor, used by the RIDE and the buyer email. Uploading an issuer logo is planned. The RIDE template (modern, classic or minimal) is chosen per account in the console; see RIDE and email.