Ir al contenido

Emisores, establecimientos y puntos de emisión

Un emisor es un contribuyente (RUC) que emite comprobantes. Una cuenta puede tener varios emisores. Cada emisor tiene establecimientos (códigos de tres dígitos como 001, tal como constan en el RUC) y cada establecimiento tiene puntos de emisión (001, 002, …). Junto con el secuencial forman el número del comprobante: 001-001-000000123.

Administrar emisores, establecimientos y puntos de emisión por la API requiere una llave read_write con alcance account, también para leerlos. La consola administra los mismos recursos en Emisores, y en ella un emisor solo se agrega desde su certificado (Nuevo emisor).

Operación Endpoint
Crear un emisor desde su certificado .p12 POST /v1/issuer-onboardings, GET /v1/issuer-onboardings/{onboardingId}, POST .../{onboardingId}/complete
Crear, listar emisores POST, GET /v1/issuers
Leer, actualizar, eliminar un emisor GET, PATCH, DELETE /v1/issuers/{issuerId}
Crear, listar establecimientos POST, GET /v1/issuers/{issuerId}/establishments
Leer, actualizar, eliminar un establecimiento GET, PATCH, DELETE /v1/issuers/{issuerId}/establishments/{establishmentId}
Crear, listar puntos de emisión POST, GET .../establishments/{establishmentId}/emission-points
Leer, eliminar un punto de emisión GET, DELETE .../emission-points/{emissionPointId}

La forma más corta de agregar un emisor es subir solo su firma electrónica (.p12) y su contraseña. Flashpi verifica el certificado, lee de él el RUC y el titular, te propone el RUC y la razón social para que revises y completes el perfil tributario y, al completar, crea el emisor con su establecimiento 001 y su punto de emisión 001. El mismo certificado sirve para pruebas y producción, así que no hace falta subirlo dos veces. La consola hace estos pasos en Emisores, Nuevo emisor.

Funciona con una llave read_write con alcance account de cualquier ambiente.

Ventana de terminal
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"

El archivo y la contraseña tienen los mismos límites que en la carga de un certificado y se cifran apenas llegan; la huella de la Idempotency-Key no incluye la contraseña. La respuesta es 202 Accepted, con el encabezado Location del alta, que empieza en 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"
}
Ventana de terminal
curl https://api.flashpi.com.ec/v1/issuer-onboardings/01a0fd70-2b4c-7d1e-9f3a-5c6b7d8e9f01 \
-H "Authorization: Bearer $FLASHPI_API_KEY"

Vuelve a leerla cada pocos segundos mientras su status sea verifying (la verificación suele tardar menos de un minuto):

status Qué significa
verifying Flashpi verifica la contraseña, la clave de firma, la vigencia, la cadena y la revocación, como en la verificación de un certificado.
ready El certificado es válido: el alta trae sus datos y se puede completar.
rejected rejection.code y rejection.message dicen por qué, con los mismos códigos que un certificado rechazado. Corrige la causa e inicia otra alta.
completed Ya se completó; completed tiene los ID del emisor y del certificado.
expired No se completó en 6 días y ya no se puede completar; su archivo cifrado se elimina automáticamente poco después (unos 7 días después de subirlo). Inicia otra alta.

Flashpi elimina un alta 30 días después de que se completa, vence o se rechaza; desde entonces GET /v1/issuer-onboardings/{onboardingId} responde 404 not_found. Guarda los ID de la respuesta de complete, o lee el emisor con GET /v1/issuers/{issuerId}, en lugar de volver a leer el alta.

Un alta lista de una empresa:

{
"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"
}
Campo Notas
certificate Datos públicos del certificado, sin material de firma: su serie, su vigencia, la entidad que lo emitió, el titular (commonName) y su empresa (organization), y la identificación que trae.
proposedRuc, rucNeedsConfirmation El RUC con el que se completa. Cuando no viene del propio certificado, rucNeedsConfirmation es true y debes confirmarlo (consulta RUC de una persona natural). proposedRuc es null cuando el certificado no trae un RUC ni una cédula (consulta Certificado sin RUC).
existingIssuer El emisor de tu cuenta que ya tiene ese RUC, si existe: completar renueva su certificado (consulta Renovación).
sri La consulta al registro de RUC del SRI, hoy desactivada (status: "disabled"). Consulta Datos del SRI.
prefill Los valores para empezar el perfil: el RUC y la razón social, que es la organization del certificado de una empresa o el commonName de una persona. El nombre comercial, la dirección matriz y el perfil tributario solo vienen del SRI, así que hoy son null y los escribes tú. null donde no se sabe nada.

Envía el emisor con los mismos campos que Crear un emisor, partiendo de prefill, corrigiendo lo que haga falta y completando lo que falte. Los números de resolución de contribuyente especial y de agente de retención los escribes tú.

Ventana de terminal
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
}
}'

La respuesta es 201 Created con el emisor y su certificado, con el encabezado Location del emisor. El emisor ya tiene el establecimiento 001 en su dirección matriz y el punto de emisión 001. El certificado sirve para pruebas y producción (allModes: true) y empieza en processing, como cualquier certificado: léelo bajo el emisor hasta que esté 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 Cuándo
409 issuer_onboarding_not_ready El alta todavía está en verifying.
409 issuer_onboarding_rejected El certificado fue rechazado.
409 issuer_onboarding_completed El alta ya se completó.
409 issuer_onboarding_expired Pasaron 6 días sin completarla.
409 issuer_already_exists Otra solicitud creó mientras tanto un emisor con este RUC. El alta sigue ready: completarla de nuevo renueva ese emisor (consulta Renovación).
422 validation_failed Falta un campo de un emisor nuevo, o el ruc es obligatorio o no coincide con el certificado (ruc_mismatch en errors).

El certificado de una persona natural suele traer su cédula, no un RUC. Flashpi propone entonces la cédula seguida de 001 (identification.rucSource: "cedula", rucNeedsConfirmation: true), y al completar debes enviar el ruc: el propuesto, u otro cuyos 10 primeros dígitos sean la cédula. Otro RUC recibe 422 con ruc_mismatch en el campo ruc. Para un certificado con la cédula 1700000001:

{
"ruc": "1700000001001",
"legalName": "PEREZ LOPEZ JUAN CARLOS",
"headOfficeAddress": "Av. Naciones Unidas E7-10, Quito",
"taxProfile": { "keepsAccounting": false, "rimpeRegime": "entrepreneur" }
}

Cuando el RUC viene del propio certificado (rucSource: "certificate"), ruc se puede omitir; si lo envías, debe ser ese RUC.

Algunos certificados no traen un RUC ni una cédula que Flashpi pueda leer. El alta lista tiene entonces proposedRuc: null, rucNeedsConfirmation: true y sri: null, porque no había un RUC que consultar al SRI, y prefill solo trae lo que se lee del certificado. Al completar debes enviar el ruc, de 13 dígitos terminados en 001 (si falta, 422 con el ruc obligatorio). Flashpi no puede compararlo con el certificado, así que asegúrate de que sea el RUC del titular. Si tu cuenta ya tiene un emisor con ese RUC, completar renueva su certificado y basta con enviar el ruc; si no, envía también los campos de un emisor nuevo.

Si tu cuenta ya tiene un emisor con el RUC del certificado, el alta trae existingIssuer y completarla renueva su certificado: no se crea otro emisor, y el cuerpo puede ser {}. El perfil del emisor no cambia; actualízalo con PATCH /v1/issuers/{issuerId} si hace falta. El certificado nuevo sirve para pruebas y producción y toma el relevo en cuanto se acepta (consulta Qué certificado firma).

Hoy Flashpi no consulta el registro público de RUC del SRI: sri.status es disabled y prefill solo trae el RUC y la razón social que se leen del certificado. La información tributaria es tu responsabilidad: revisa y completa cada valor antes de completar el alta.

Cuando la consulta se active, Flashpi la hará una sola vez, después de verificar el certificado, con el RUC propuesto, y prefill tomará del SRI la razón social, el nombre comercial, la dirección matriz y el perfil tributario. sri traerá entonces lo que respondió el SRI:

{
"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.status es found, not_found (el SRI no tiene ese RUC: revisa que sea correcto), unavailable (el SRI no respondió) o disabled (no se consultó). sri es null cuando el certificado no dio un RUC que consultar (consulta Certificado sin RUC). Cuando no hay perfil, prefill solo trae lo que se lee del certificado y completas el resto.
  • sri.warnings avisa cuando el RUC no está ACTIVO (inactive), cuando el SRI marca al contribuyente como fantasma (ghost) o por transacciones inexistentes (nonexistent_transactions), o cuando su matriz figura cerrada (head_office_closed). Son solo avisos: nunca impiden completar el alta.
  • profile.rimpeRegime es entrepreneur, popular_business, general (fuera del RIMPE) o unknown (no se pudo interpretar: elige tú el régimen). general se envía al completar como rimpeRegime: null, y el SRI solo dice si el contribuyente es contribuyente especial o agente de retención: los números de resolución los escribes tú.

También puedes crear un emisor con JSON, sin subir su certificado: sigue funcionando igual, y luego subes el certificado por separado (consulta Certificados). La consola ya no ofrece esta forma.

Ventana de terminal
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
}'

La respuesta es 201 Created con el emisor:

{
"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"
}
Campo Notas
ruc 13 dígitos terminados en 001. Solo se valida el formato: los RUC más nuevos no cumplen el antiguo dígito verificador módulo 11, así que Flashpi nunca lo verifica. No puede cambiar después, y una cuenta no puede registrar el mismo RUC dos veces (409 issuer_already_exists; con el alta desde el certificado, el mismo RUC renueva el emisor).
legalName, tradeName La razón social tal como consta en el RUC, y el nombre comercial opcional. El correo al comprador muestra el nombre comercial, o la razón social, como remitente.
headOfficeAddress La dirección matriz.
taxProfile Consulta Perfil tributario.
branding.brandColor El color de marca del RIDE y del correo al comprador, #RRGGBB (se devuelve en minúsculas).
sendEmailByDefault Si los comprobantes autorizados se envían por correo al comprador cuando la solicitud no lo indica (options.sendEmail). true por defecto. Consulta RIDE y correo.

El perfil tributario se configura una sola vez, en el emisor. Flashpi escribe las etiquetas y leyendas que correspondan en cada comprobante, así que las solicitudes nunca las repiten.

Campo Lo que Flashpi agrega a los comprobantes
keepsAccounting (obligatorio) Si el contribuyente está obligado a llevar contabilidad.
specialTaxpayerNumber El número de resolución de contribuyente especial, de 3 a 13 letras o dígitos. Los comprobantes de retención aceptan máximo 5 caracteres (incompatible_issuer_profile si no).
withholdingAgentResolution El número de resolución de agente de retención, solo dígitos.
rimpeRegime entrepreneur imprime CONTRIBUYENTE RÉGIMEN RIMPE y popular_business imprime CONTRIBUYENTE NEGOCIO POPULAR - RÉGIMEN RIMPE. null fuera del RIMPE.
largeTaxpayerResolution La resolución de gran contribuyente, impresa como el campo adicional Gran Contribuyente.

Flashpi también agrega a cada comprobante el campo adicional RUC Proveedor: el RUC del proveedor registrado de facturación electrónica, Signia Digital S.A. (0993411372001). Un comprobante admite máximo 15 campos adicionales, así que estas leyendas ocupan uno o dos, y sus nombres están reservados en tu additionalInfo (reserved_name).

Ventana de terminal
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" }'
Ventana de terminal
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" }'
  • Un establecimiento tiene un code de tres dígitos, tal como consta en el RUC, y una address que se imprime en sus comprobantes. Solo la dirección puede cambiar después (PATCH).
  • Un punto de emisión tiene un code de tres dígitos y nada más que cambiar.
  • Un código ya usado recibe 409 establishment_already_exists o emission_point_already_exists.
  • Las listas de establecimientos y de puntos de emisión se ordenan por código; la de emisores, del más nuevo al más antiguo. Consulta Paginación.

Los comprobantes indican el establecimiento y el punto de emisión por sus códigos ("establishment": "001"), no por sus ID.

Flashpi asigna el siguiente secuencial de forma atómica por emisor, establecimiento, punto de emisión y tipo de comprobante, así que dos solicitudes simultáneas nunca reciben el mismo número, y genera la clave de acceso de 49 dígitos con un código numérico aleatorio. Las facturas y las notas de crédito de un mismo punto de emisión tienen series separadas.

Una solicitud puede enviar su propio sequential (de 1 a 999.999.999), por ejemplo para continuar la numeración del sistema del que migras:

  • No debe estar usado por otro comprobante del mismo tipo y serie (409 sequential_already_used).
  • Si es mayor que el último, los secuenciales automáticos siguientes continúan después de él. Un secuencial libre menor llena un hueco y no mueve el contador.
  • Una serie que llegó a 999.999.999 recibe 409 sequentials_exhausted.
  • El emisor demo compartido nunca acepta uno.
  • PATCH /v1/issuers/{issuerId} cambia los campos que envíes; null borra un campo opcional. El RUC nunca cambia.
  • DELETE /v1/issuers/{issuerId} elimina el emisor con sus establecimientos, puntos de emisión y API keys de ese emisor. Se rechaza con 409 resource_in_use mientras haya comprobantes o certificados que lo usen, así que un emisor que emitió comprobantes se queda.
  • Tampoco se puede eliminar un establecimiento o punto de emisión con comprobantes (409 resource_in_use).

Hoy la marca de un emisor es su brandColor, que usan el RIDE y el correo al comprador. Subir un logo del emisor está planificado. La plantilla del RIDE (modern, classic o minimal) se elige por cuenta en la consola; consulta RIDE y correo.