Skip to content

Authentication and API keys

Every request to the invoicing API carries an API key as a Bearer token. The only route without a key is GET /v1/status.

Terminal window
curl https://api.flashpi.com.ec/v1/documents \
-H "Authorization: Bearer $FLASHPI_API_KEY"
Prefix Environment What it is for
fp_test_ SRI test environment (ambiente 1) Development, automated tests and the sandbox. Documents have no tax effect.
fp_live_ SRI production (ambiente 2) Documents with tax effect.

Both kinds call the same API at https://api.flashpi.com.ec. The key decides the environment, and each environment is kept apart: a test key only sees test documents, test certificates, test webhook endpoints and test events, and a live key only live ones. A certificate uploaded through the onboarding from the certificate serves both environments, so both keys see it. Idempotency keys are separate per environment too.

A key looks like fp_test_ or fp_live_, then a 16-character public ID, then a 32-character secret (56 characters, letters and digits only). The public ID is not secret: the console and the request logs show it so you can tell keys apart. Flashpi stores only a SHA-256 hash of the whole key, so nobody, Flashpi included, can show it again after it is created.

API keys are created in the console, under API keys; the API has no endpoint to create them. Each key has a name, an environment, a scope, an access level and an optional IP allowlist. The whole key is shown once, when it is created.

  • Test keys can be created by account owners and by members with read and write access to every issuer.
  • Live keys can only be created by account owners, who confirm with their authenticator code (two-factor authentication is mandatory for owners). The account first needs an issuer of its own, not the demo issuer, with an accepted signing certificate. See Issuers and Certificates.

The scope and the access level cannot change after a key is created; its name and its IP allowlist can. To change the rest, create a new key and revoke the old one.

  • account: every issuer of the account, including issuers added later.
  • issuer: one issuer (one RUC). The key can only issue and read the documents and events of that issuer.

An issuer-scoped key gets 403 with the code key_scope_mismatch when it names another issuer, or calls a route that belongs to the whole account: managing issuers, establishments, emission points, certificates and webhook endpoints. The shared demo issuer also needs an account-scoped key.

  • read_write: can issue documents, email them again and, with account scope, manage the configuration.
  • read_only: can read documents, their XML and RIDE, and events. Anything that writes answers 403 with the code key_read_only.

Managing issuers, establishments, emission points, certificates and webhook endpoints needs an account-scoped read_write key, also to read them.

A key can be limited to a list of up to 20 IPv4 or IPv6 addresses or CIDR ranges, such as 203.0.113.10 or 2001:db8::/48. An empty list allows any address.

  • The address checked is the one your request arrives from at Flashpi’s edge: the public address of your server or of its NAT gateway, not a private one.
  • A request from any other address gets 403 with the code ip_not_allowed, and the detail names the address Flashpi saw, so you can add it.
  • A range with host bits set (10.0.0.1/8) is refused as a likely typo. Write the network address (10.0.0.0/8) instead.
  • Changing the allowlist of a live key in the console asks for your authenticator code.
Situation Answer
No Authorization header, or not a Bearer token 401 authentication_required
Malformed, unknown or revoked key 401 invalid_api_key
The account is suspended 403 account_suspended
The client IP is not in the key’s allowlist 403 ip_not_allowed
An issuer-scoped key on another issuer or an account-wide route 403 key_scope_mismatch
A read_only key on a route that writes 403 key_read_only

Both 401 answers carry WWW-Authenticate: Bearer realm="flashpi", with error="invalid_token" added for invalid_api_key. A malformed, unknown and revoked key get the same code on purpose, so the answer never reveals which keys exist. Every error body follows the format in Errors.

  • Keep keys on your servers. Never put a key in a web page, a mobile app, a desktop app you distribute or a public repository. Anyone with the key can issue documents in your name.
  • Store them as secrets. Read the key from an environment variable or a secret manager, not from your source code. Keep live keys out of development machines and CI.
  • One key per system and environment. A separate key for each service (your shop, your ERP, a reporting job) lets you revoke one without stopping the others, and the request logs show which one called.
  • Give each key the least it needs. Use an issuer-scoped key for a system that only issues for one RUC, and a read_only key for reporting and reconciliation.
  • Add an IP allowlist when your servers have fixed public addresses.
  • Never log the key. Leave the Authorization header out of your logs and error reports. To identify a key, use its public ID.
  • Rotate without downtime. Create the new key, deploy it, check in the console’s request logs that the old key is no longer used, then revoke it.
  • Revoke a leaked key at once. Revoking takes effect immediately and never asks for an authenticator code, so a leaked key can be stopped right away. Revoking a live key emails every account owner.