Test webhooks locally

With the fiscalapi CLI, you receive the events of your tenant (the space in Fiscalapi that holds your issuers, recipients, credits, and data) on your computer, trigger test events, and resend the ones you missed, without exposing your server to the internet.

How it works

  1. fiscalapi listen opens your CLI listener: a webhook without a URL, one per person (any individual or legal entity registered in your tenant), with its own signing secret.
  2. When an event occurs in your tenant, or when you trigger one, the Fiscalapi server generates it, signs it with your listener's secret, and creates a delivery for the listener.
  3. The CLI picks up the delivery and forwards it to your local server as a POST with the exact body and the signed headers.
  4. Your server verifies the signature and responds, the same as with a URL webhook.

Your computer doesn't generate the events or need a public URL: the CLI requests the deliveries from Fiscalapi and forwards them to localhost.


Install the CLI

fiscalapi is a single binary for Windows, Linux, and macOS; you don't need to install .NET. Download the package for your system and the SHA256SUMS file from GitHub Releases, and verify the SHA-256 before you run it.

SystemPackage
Windows x64fiscalapi-win-x64.zip
Linux x64, glibc 2.28 or laterfiscalapi-linux-x64.tar.gz
macOS Apple Siliconfiscalapi-osx-arm64.tar.gz
macOS Intelfiscalapi-osx-x64.tar.gz

Linux

base=https://github.com/FiscalAPI/fiscalapi-cli/releases/latest/download
curl -fsSLO "$base/fiscalapi-linux-x64.tar.gz"
curl -fsSLO "$base/SHA256SUMS"
grep ' fiscalapi-linux-x64.tar.gz$' SHA256SUMS | sha256sum -c -   # should print: OK
tar -xzf fiscalapi-linux-x64.tar.gz
sudo install -m 0755 fiscalapi /usr/local/bin/fiscalapi
fiscalapi --version

macOS

package=fiscalapi-osx-arm64.tar.gz   # on an Intel Mac: fiscalapi-osx-x64.tar.gz
base=https://github.com/FiscalAPI/fiscalapi-cli/releases/latest/download
curl -fsSLO "$base/$package"
curl -fsSLO "$base/SHA256SUMS"
grep " $package\$" SHA256SUMS | shasum -a 256 -c -   # should print: OK
tar -xzf "$package"
sudo mkdir -p /usr/local/bin
sudo install -m 0755 fiscalapi /usr/local/bin/fiscalapi
fiscalapi --version

Windows (PowerShell)

$base = 'https://github.com/FiscalAPI/fiscalapi-cli/releases/latest/download'
Invoke-WebRequest "$base/fiscalapi-win-x64.zip" -OutFile fiscalapi-win-x64.zip
Invoke-WebRequest "$base/SHA256SUMS" -OutFile SHA256SUMS
$expected = (Select-String -Path SHA256SUMS -Pattern ' fiscalapi-win-x64\.zip$').Line.Split(' ')[0]
$actual = (Get-FileHash fiscalapi-win-x64.zip -Algorithm SHA256).Hash.ToLowerInvariant()
if ($actual -ne $expected) { throw "El SHA-256 no coincide: $actual" } else { 'SHA-256 OK' }

$dir = Join-Path $env:LOCALAPPDATA 'Programs\fiscalapi'
Expand-Archive fiscalapi-win-x64.zip -DestinationPath $dir -Force

The check must print OK. If it prints FAILED or the hashes don't match, delete what you downloaded and download it again.

These commands install the latest published version. To install a specific version, replace releases/latest/download with releases/download/v0.1.0.

The CLI repository explains how to add the CLI to the PATH on Windows, what to do if Gatekeeper or SmartScreen blocks it, and how to update and uninstall it.

Sign in

Terminal

$ fiscalapi login
API key:
Tenant key:
Listo. Credenciales guardadas para test.fiscalapi.com.

The command asks for your API key and your tenant key without displaying them, validates them with the API, and saves them in your system's credential store. It works in the test environment by default; for production, use fiscalapi login --live. To get your keys, see Get your credentials.

The API key needs the Webhooks.Manage permission. Without it, listen, trigger, and the webhooks commands return 403, and login warns you when it saves the keys.

On Linux without a credential store (WSL, a server without a desktop, or a container), login ends with No hay un almacén de credenciales disponible en este sistema. (No credential store is available on this system.) In that case, set the FISCALAPI_API_KEY and FISCALAPI_TENANT_KEY environment variables, both of them, and don't use login.

Receive events on your local server

Terminal 1

$ fiscalapi listen --forward-to http://localhost:3000/webhooks
Listo. Tu secreto de firma es whsec_… (escucha 9b2e7c4a-1d3f-4e6b-8a5c-0f1e2d3c4b5a)
2026-10-12 09:47:46  --> invoice.canceled [3f9c1d2e-7b4a-4e8f-9a1b-2c3d4e5f6a7b] [200]

Replace the URL with the route on your server that receives webhooks. Each line shows the local time, the type, the event id (the webhook-id header), and what your server responded:

End of the lineWhat it means
[200]Your server responded with that code.
[error: Timeout]Your server didn't respond within 15 seconds.
[error: ConnectionFailed]The CLI couldn't connect: nothing is listening at that URL, or the connection was refused.
[error: TlsFailed]TLS to your server failed, for example with a self-signed certificate.

listen runs until you stop it with Ctrl+C.

OptionWhat it does
--forward-to <url>The http or https URL of your server. Without it, listen only shows the events in the terminal.
--events <types>Only these types, separated by commas, for example invoice.canceled,invoice.cancellation_rejected. By default, all of them.
--skip-verifyDoesn't verify your server's TLS certificate. It never affects the connection to Fiscalapi.

Verify the deliveries

Configure your server with the whsec_… secret that listen prints, and verify each delivery like any other, over the raw body: Verify the signature. It's the secret of your CLI listener, different from the secrets of your URL webhooks and stable across restarts, so you configure it once.

To put it in an environment variable without copying it from the terminal:

export FISCALAPI_WEBHOOK_SECRET=$(fiscalapi listen --print-secret)

With --print-secret, the CLI opens a session the same way listen does. Run it before you start listen, not while it's running.

Trigger a test event

With listen running, trigger an event from another terminal:

Terminal 2

$ fiscalapi trigger invoice.canceled
Evento disparado: 3f9c1d2e-7b4a-4e8f-9a1b-2c3d4e5f6a7b al webhook 9b2e7c4a-1d3f-4e6b-8a5c-0f1e2d3c4b5a.

The event has the shape and the signature of a real event of its type, and it reaches only your listener, even if its type isn't in your --events. You can trigger any event type except webhook.test.

OptionWhat it does
--related-object-id <id>The id of a real resource in your tenant, so your server can retrieve it. Without it, the event carries a synthetic id, and the GET to relatedObject.url returns 404.
--person-id <id>The person in your tenant that owns the resource. By default, the event has no person.
--webhook <id>Delivers the event to that URL webhook instead of your listener.

It works only in the test environment: with --live, it returns 403 with the detail fiscalapi trigger no está disponible en producción; usa el ambiente de pruebas. (fiscalapi trigger isn't available in production; use the test environment.) Without --webhook or a running listen, it returns 409.

Resend an event

Find the event with fiscalapi events list and resend it to your listener:

Terminal 2

$ fiscalapi events resend 3f9c1d2e-7b4a-4e8f-9a1b-2c3d4e5f6a7b
Reenvío creado: entrega d1e2f3a4-b5c6-4d7e-8f9a-0b1c2d3e4f5a al webhook 9b2e7c4a-1d3f-4e6b-8a5c-0f1e2d3c4b5a.

Without --webhook, the resend goes to your listener and needs a running listen; otherwise, it returns 409. It arrives with the same webhook-id and the same body, so your deduplication recognizes it.

Good to know

SituationWhat happens
You trigger an eventThe Fiscalapi test server generates it, not your computer. It appears in the event list and you can resend it like any other.
listen is closed or offlineThe events from that time don't reach it later. Recover them with fiscalapi events resend.
Your server fails a listener deliveryThere are no retries: the delivery keeps that result. Repeat it with fiscalapi events resend.
You open another listen with the same personThere's only one session per person: the new one replaces the previous one, which ends with a 409.
You trigger or resend a test event to a URL webhook that is failingIts 2xx doesn't end the failure streak: the webhook keeps adding up its 5 days without successful responses.

CLI reference

fiscalapi --help and fiscalapi <command> --help describe each option. The full reference, with the JSON output, the exit codes, and troubleshooting, is in the CLI repository.

Was this page helpful?