Skip to content

Developer portal

Integrate Firstguard payments into your shop or app

One REST API, ready-made shop plugins and a free sandbox. Accept Pay by Bank, QR payments and payment links – with the money on your account in seconds and a webhook that tells your system the moment it arrives.

  • Free sandbox with a test bank
  • Plugins for WooCommerce, Magento and Shopware
  • Signed webhooks, real-time status

How an integration works

Four steps from "Pay now" to money on your account. Your system only talks to us; we talk to the customer's bank.

  1. 1

    Your shop creates a payment

    One API call with the amount, your order number and the page to return to. You get a checkout link and a QR code back.

  2. 2

    The customer opens it

    Online: your shop redirects to the checkout link. In store: the customer scans the QR code with their banking app or the Firstguard app.

  3. 3

    They approve in their bank app

    The customer confirms with fingerprint or face ID. No card number, no form to fill in, nothing to type.

  4. 4

    You get a webhook

    We call your server with the result (payment.paid). Ship the order – the money is already on your account.

Everything you can build with the API

Pick the building blocks you need. They share the same account, merchant panel and webhooks.

Checkout API

Create a payment, redirect the customer, receive a webhook when the money has arrived. Three calls, no card forms, no PCI scope.

Payment links & buttons

Generate links from the merchant panel or programmatically for invoices, quotes, e-mails and chat. Single-use or reusable, with expiry dates.

QR codes

Every payment has a QR code endpoint that returns a PNG. Show it on a screen, a kiosk, a receipt or a printed poster.

Shop plugins

Official modules for WooCommerce, Magento and Shopware. Install, paste your API key, set the webhook, go live.

Refunds & reports

Full or partial refunds and daily settlement reports (CSV / JSON) through the same API and the merchant panel.

Sandbox

An isolated test environment with a simulated bank, so you can test every step – including rejected payments – before the first real euro.

Documentation

Integration guides

Getting started

Introduction

The Firstguard API lets you accept account-to-account payments (Pay by Bank) in your shop, app or point of sale. Everything runs over HTTPS with JSON bodies. You authenticate every request with an API key, create payments with a single call and receive the outcome on a webhook – no polling required.

Production APIhttps://api.firstguardpayments.com
Sandbox APIhttps://api.sandbox.firstguardpayments.com
Merchant panelhttps://merchant.firstguardpayments.com
Sandbox panelhttps://merchant.sandbox.firstguardpayments.com

All amounts are in euro with two decimals (48.00). Timestamps are ISO 8601 in UTC. Identifiers you receive from us (payment IDs, transaction IDs) are stable and safe to store.

Getting started

Using the sandbox environment

The sandbox is a complete copy of production where no real money moves. Use it to build and test your integration, then switch the two URLs to go live.

  1. Create a sandbox account at https://merchant.sandbox.firstguardpayments.com. When a one-time code is requested, use 123456.
  2. Point your API client at https://api.sandbox.firstguardpayments.com. Every endpoint of the reference is available there.
  3. Pay test payments with the built-in Firstguard Test Bank. Choose "Approve" or "Reject" on the test bank screen to simulate both outcomes.

Sandbox payments are limited to a maximum of €10 per payment. Sandbox and production are fully separated: keys, webhooks and data never cross over.

Getting started

Getting API keys

API keys are created in the merchant panel. Sandbox keys start with fg_test_, production keys with fg_live_.

  1. Log in to the merchant panel and open Settings → API.
  2. Click Add API key, give it a name (for example "Webshop") and copy the key. It is shown only once.
  3. Send the key in the X-Api-Key header of every request.
Authentication header
X-Api-Key: fg_test_9f1c2a7e4b8d4c0e9a3f6b2d1e5c7a9b

Keep keys secret. Never put them in front-end code, mobile apps or public repositories. You can revoke a key at any time in the panel; create a separate key per system so you can rotate them independently.

Receive payments

Create a payment with the API

Send the amount, your own order reference and the URLs to return to. The response contains a redirectUrl for the customer, a paymentId for later look-ups and an expiry time (payments expire after 15 minutes by default).

POST /v1/payments
curl -X POST https://api.sandbox.firstguardpayments.com/v1/payments \
  -H "X-Api-Key: fg_test_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "orderId": "order-1042",
    "amount": 48.00,
    "currency": "EUR",
    "languageCode": "en",
    "successUrl": "https://yourshop.com/thank-you",
    "cancelUrl": "https://yourshop.com/cart",
    "payerName": "Anna Schmidt"
  }'

Response 201 Created

response.json
{
  "paymentId": "pay_7Hk2mQ9xL4",
  "transactionId": "b3b8f8e2-9c2e-4c1a-8e2d-3f7b8e2c9c2e",
  "status": "initialized",
  "redirectUrl": "https://pay.firstguardpayments.com/c/7Hk2mQ9xL4",
  "qrCodeUrl": "https://api.sandbox.firstguardpayments.com/v1/payments/pay_7Hk2mQ9xL4/qr-code",
  "expiresAt": "2026-09-02T14:36:07Z"
}

After the customer has paid, they are sent back to your successUrl. Do not ship on the redirect alone – wait for the payment.paid webhook, or check the status with GET /v1/payments/{paymentId}.

Receive payments

QR codes for in-store and kiosk payments

Every payment has a QR code. Request it as a PNG and show it on a customer display, a tablet at the counter or a self-service kiosk. The customer scans it with their banking app or the Firstguard app and approves.

GET /v1/payments/{paymentId}/qr-code
curl https://api.sandbox.firstguardpayments.com/v1/payments/pay_7Hk2mQ9xL4/qr-code?size=512 \
  -H "X-Api-Key: fg_test_your_key" \
  --output qr.png

The QR code stays valid until the payment expires. For a counter that is always ready, create a new payment per transaction; for a fixed amount (tips, donations, a menu item) create a reusable payment link instead.

Webhooks

Receiving webhooks

Webhooks are HTTP POST requests we send to your server whenever a payment changes status. Register an endpoint in the merchant panel under Settings → API → Webhooks (or with POST /v1/webhooks), choose the events you want and save. We retry failed deliveries with increasing intervals for up to 24 hours.

EventWhen it is sent
payment.initializedThe payment was created and is waiting for the customer.
payment.pendingThe customer has approved; the bank is processing the transfer.
payment.paidThe money has arrived on your account. Safe to ship.
payment.rejectedThe customer cancelled or the bank declined.
payment.erroredA technical error occurred; the customer can try again.
payment.refundedA refund you issued was executed.
Webhook payload
{
  "event": "payment.paid",
  "paymentId": "pay_7Hk2mQ9xL4",
  "transactionId": "b3b8f8e2-9c2e-4c1a-8e2d-3f7b8e2c9c2e",
  "orderId": "order-1042",
  "amount": 48.00,
  "currency": "EUR",
  "status": "paid",
  "statusMessage": "Accepted by bank",
  "date": "2026-09-02T14:21:07Z"
}

Respond with HTTP 200 within 10 seconds. Handle events idempotently: the same event can be delivered more than once, so use paymentId and status to decide whether you have processed it already.

Webhooks

Webhook signature verification

Every webhook carries an X-Signature header: an HMAC-SHA256 of the raw request body, created with the secret key shown next to your webhook in the merchant panel. Verify it before you trust the payload.

webhook.js
const crypto  = require("crypto");
const express = require("express");
const app = express();

app.post("/webhooks/firstguard", express.raw({ type: "application/json" }), (req, res) => {
  const expected = crypto
    .createHmac("sha256", process.env.FIRSTGUARD_WEBHOOK_SECRET)
    .update(req.body)
    .digest("hex");

  const received = req.headers["x-signature"] || "";
  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
    return res.status(400).send("invalid signature");
  }

  const event = JSON.parse(req.body);
  if (event.status === "paid") {
    markOrderAsPaid(event.orderId);   // your code
  }
  res.sendStatus(200);
});

Plugins

WooCommerce plugin

Adds "Firstguard – Pay by Bank" as a payment method to the WooCommerce checkout. Orders are marked as paid automatically through the webhook.

  1. Install the plugin. Download it from the merchant panel (Settings → Plugins), upload it under Plugins → Add new → Upload in WordPress and activate it.
  2. Enter your credentials. Go to WooCommerce → Settings → Payments → Firstguard, enable the method and paste your API key. Tick "Sandbox mode" while testing.
  3. Set up the webhook. Copy the webhook URL shown on the settings page (https://yourshop.com/?wc-api=firstguard) into the merchant panel and paste the secret key back into the plugin.

Plugins

Magento 2 plugin

  1. Install the module. Download it from the merchant panel and install it with Composer, then run bin/magento setup:upgrade and bin/magento cache:flush.
  2. Enter your credentials. Under Stores → Configuration → Sales → Payment Methods → Firstguard, enable the method, choose Sandbox or Production and paste the matching API key.
  3. Set up the webhook. Register https://yourshop.com/firstguard/webhook in the merchant panel and paste the secret key into the module configuration.

Plugins

Shopware 6 plugin

  1. Install the plugin. Upload the ZIP under Extensions → My extensions → Upload extension, then install and activate it.
  2. Enter your credentials. Open the extension configuration, paste your API key and select the sales channels that should offer Firstguard.
  3. Assign the payment method. Under Settings → Payment methods, activate "Firstguard – Pay by Bank" and add it to your sales channel.
  4. Set up the webhook. Register https://yourshop.com/firstguard/webhook in the merchant panel and paste the secret key into the plugin configuration.

Reference

Errors, idempotency & limits

Errors use standard HTTP status codes with a JSON body that explains what went wrong:

Error response (400)
{
  "error": {
    "code": "validation_error",
    "message": "amount must be greater than 0",
    "field": "amount"
  }
}
StatusMeaning
400Invalid request – see error.field.
401Missing or invalid API key.
404Payment or webhook not found.
409Duplicate Idempotency-Key with a different body.
429Rate limit reached (600 requests per minute per key). Retry after the Retry-After header.
5xxTemporary problem on our side – safe to retry with the same idempotency key.

Send an Idempotency-Key header (any unique string, for example your order number) with POST requests. If a request times out, repeat it with the same key and you will never create a payment twice.

API reference

Firstguard Payments API v1

Base URL https://api.firstguardpayments.com · Authentication X-Api-Key header · JSON in, JSON out

Payments

  • POST/v1/paymentsCreate a payment and receive a checkout link and QR code.
  • GET/v1/payments/{paymentId}Retrieve the current status and details of a payment.
  • GET/v1/payments/{paymentId}/qr-codePNG image of the payment QR code (size 128–1024 px).
  • GET/v1/payments/{paymentId}/pay-urlFresh checkout URL for an open payment, optionally with a new returnUrl.
  • POST/v1/payments/{paymentId}/refundsRefund a paid payment fully or partially (amount optional).
  • GET/v1/paymentsList payments, filter by status, from and to. Paginated.

Payment links

  • POST/v1/payment-linksCreate a reusable or single-use payment link.
  • GET/v1/payment-links/{linkId}Retrieve a link and the payments made through it.
  • DELETE/v1/payment-links/{linkId}Deactivate a link.

Webhooks & reports

  • POST/v1/webhooksRegister a webhook endpoint; returns the signing secret.
  • GET/v1/webhooksList registered endpoints.
  • DELETE/v1/webhooks/{webhookId}Remove an endpoint.
  • GET/v1/settlementsDaily settlement reports (JSON or CSV with Accept: text/csv).
POST/v1/paymentsCreate a payment

Headers

X-Api-Key required
Your sandbox or production API key.
Idempotency-Key optional
Unique string to make retries safe.

Request body

orderId string required
Your own reference; returned in every webhook.
amount number required
Amount in euro with two decimals, e.g. 48.00. Minimum 0.01.
currency string
ISO 4217 code. Currently EUR.
languageCode string
Language of the checkout page: en, de, fr, it. Default en.
successUrl string required
Where the customer is sent after approving.
cancelUrl string required
Where the customer is sent after cancelling.
payerName string
Pre-fills the payer name on the checkout page.
description string
Shown to the customer and on the bank statement (max. 140 characters).
expiresIn integer
Validity in seconds, 60–86400. Default 900.

Response 201

paymentId string
Identifier for look-ups, QR codes and refunds.
transactionId string
UUID of the underlying bank transaction.
status string
initialized, pending, paid, rejected, errored, expired, refunded.
redirectUrl string
Checkout page for the customer.
qrCodeUrl string
PNG endpoint of the QR code.
expiresAt string
ISO 8601 timestamp.

Errors

400
Validation error – a field is missing or invalid.
401
Invalid API key.

Built for production

Bank-grade security

TLS 1.2+ on every connection, API keys you can rotate, HMAC-signed webhooks.

Regulated rails

Payments run over PSD2 open-banking connections to the customer's own bank.

Hosted in the EU

All data is processed and stored in European data centres under GDPR.

Developer support

Integration questions are answered by engineers within one business day. Contact support

Start building today

Create a free sandbox account, generate your API keys and make your first test payment in minutes. Going live is a change of two URLs.