Finqware Link API ## Sections • [🚀 Quick Start](https://developers.finqware.com/introduction/quick-start.md): Overview FinqLink and FinqData are a set of APIs for account-to-account payments/transfers and account information services through open-banking and other local/custom integrations. How to test Get a set of API test credentials (contact Finqware) Use the /test/providers/list endpoint to query for the available/supported providers. to visualize the providers list (and more) check our public dashboard . Create finq-links using the /test path: payment links using the /test/links/create endpoint consent links for account data using the /test/consents/create endpoint. Send the link to someone in order to authorize the payment or to authorize access to account data. Sandbox testing rzb_ro - debtor IBAN: RO03RZBR0000069999999999 , creditor IBAN: RO10RZBR0000069999999970 , PSU ID: 9999999998 bt_ro - username: testbt , password: testbt , pin: 1234567 cec_ro - username: testcecapi , password: testcecapi , IBAN: RO42CECEAG0202RON0007466 granit_hu - username: testuser , password: testuser , SMS code: SMS mbh_hu - username: testuser , password: testuser , SMS code: SMS • [📋 Changelog](https://developers.finqware.com/introduction/changelog.md): Version 2.0 Changelog This document outlines all changes between FinqLink API v1 and v2, including new features, enhancements, and breaking changes. Overview FinqLink v2 is a major release that introduces: FinqData - Account Information Services (AIS) for accessing bank account data Enhanced Pay APIs - Pagination, filtering, and new link statuses Custom WebUI Templates - 7 customizable UI themes for payment and consent flows Providers API Enhancements - AIS methods support and improved response formats New: Account Information Services (AIS) - FinqData The most significant addition in v2 is the complete Account Information Services (AIS) functionality, branded as FinqData . This enables bank account data access alongside existing payment initiation capabilities. New API Endpoints All AIS endpoints are available on /v2 API paths only (not available in v1): Endpoint Description POST /ais/consents/create Create a new AIS consent for data access POST /ais/consents/get Retrieve consent details and current status POST /ais/consents/revoke Revoke an active consent POST /ais/consents/redirect Handle SCA callback redirect (direct_sca flow) POST /ais/transactions/list List transactions with filtering and keyset pagination POST /ais/accounts/list List accounts with balance information POST /ais/balances/list List balance history with pagination POST /ais/jobs/create Trigger an on-demand data refresh job POST /ais/jobs/get Get data refresh job status Consent Lifecycle AIS consents follow this lifecycle: Plain Text created → started → requested → sca_url_retrieved → awaiting_authz → authorized → active For decoupled AIS methods (e.g. BRD), the user authorises in their banking app instead of a redirect: Plain Text created → started → requested → awaiting_decoupled_authz → authorized → active Terminal states: expired , revoked , deactivated , failed , suspended Scope Configuration Control what data is accessible through consent scope: Full scope: ["accounts", "balances", "transactions"] - Access to all account data Limited scope: ["accounts", "balances"] - Faster job completion, no transaction history AIS Webhooks Configure webhooks in consent creation to receive real-time updates: consent_status_update - Triggered when consent status changes (e.g., awaiting_authz → active ) job_status_update - Triggered when data refresh job completes or fails Enhanced: Links API Pagination for /links/list The /links/list endpoint now supports keyset-based pagination for efficient traversal of large result sets. Request parameters: JSON { "pagination": { "limit": 50, "after": "eyJpbnNlcnRlZF9hdCI6..." } } Parameter Type Description pagination.limit integer Maximum records per page (1-250, default: 50) pagination.after string Keyset cursor from previous response for next page Response includes: JSON { "pagination": { "count": 50, "more?": true, "after": "eyJpbnNlcnRlZF9hdCI6Li4u" }, "links": [...] } New Filter Options Filter payment links by multiple criteria: Filter Type Description filter.status string Filter by payment status (created, completed, failed, etc.) filter.inserted at from datetime Links created after this timestamp filter.inserted at to datetime Links created before this timestamp Example: JSON { "filter": { "status": "completed", "inserted_at_from": "2024-01-01T00:00:00Z" }, "pagination": { "limit": 100 } } New Payment Link Statuses Additional statuses for enhanced payment tracking (available for libra_ro, work-in-progress for other providers): Status Description funds_received Funds confirmed received by creditor bank (via webhook) funds_rejected Funds rejected by creditor bank (via webhook) Enhanced: Providers API AIS Methods Support The /providers/list and /providers/get endpoints now support AIS method discovery: New options: Option Type Description options.show ais methods boolean Include AIS method details in response options.ais methods filter.account owner type array Filter by account owner type (retail, corporate) options.ais methods filter.interface_type string Filter by interface type options.ais methods filter.interface_env string Filter by environment (sandbox, stage, prod) Example: JSON { "options": { "show_ais_methods": true, "ais_methods_filter": { "account_owner_type": ["retail"], "interface_env": "prod" } } } Response Format Change: remitter_type The remitter_type field format has changed between v1 and v2: Version Format Example v1 String "retail" or "corporate" v2 Array ["retail"], ["corporate"], or ["retail", "corporate"] This change enables payment methods to support multiple remitter types simultaneously. New: WebUI Custom Templates Customize the payment and consent authorization UI with pre-built templates. Available Templates Template Description default Standard/legacy FinqLink layout classic Traditional banking interface compact Minimal, space-efficient layout cards Card-based provider selection glass Glassmorphism design with blur effects sheet Bottom sheet mobile-first design Usage Specify the template in /links/create or /ais/consents/create : JSON { "options": { "ux_template": "glass" } } Note: The ux_template option overrides the default template configured for your API client. Breaking Changes 1. remitter_type Response Format Affected endpoints: /providers/list , /providers/get The remitter_type field in payment method responses has changed from a string to an array: v1 Response: JSON { "payment_methods": [{ "remitter_type": "retail" }] } v2 Response: JSON { "payment_methods": [{ "remitter_type": ["retail"] }] } Migration: Update your code to handle remitter_type as an array. 2. AIS Endpoints Availability AIS endpoints ( /ais/* ) are only available on /v2 paths . Requests to /v1/ais/* will return a 404 error. 3. Pagination Response Structure The /links/list endpoint now returns pagination metadata in a structured format: v1 Response: JSON { "links": [...] } v2 Response: JSON { "pagination": { "count": 50, "more?": true, "after": "cursor_token" }, "links": [...] } Migration: Update your code to extract links from the links array and handle pagination metadata. Migration Guide Upgrading from v1 to v2 Update API path: Change from /v1/ to /v2/ Handle array remitter_type : Update providers response parsing to treat remitter_type as an array Optional : If using /links/list , handle the new pagination response structure Optional - Enable AIS: Contact Finqware to enable FinqData access for your API client Optional - Customize UI: Explore the new ux_template options for branded payment experiences API Version Support Version Status End of Life v1 Supported TBD v2 Current - • [Security](https://developers.finqware.com/api-reference/security.md): The Link API is secured by OAuth2 (mandatory for production access) and mTLS (optional). Mutual TLS (mTLS) and OAuth2 Client Credentials are two distinct security mechanisms that can complement each other to provide robust authentication and secure communication in API integrations. Note: For testing purposes we also support an internal authentication method that requires client_id / client_secret with each API call. The code examples in this document use this particular method. How mTLS and OAuth2 Client Credentials Complement Each Other When used together, mTLS and OAuth2 Client Credentials Grant provide a powerful combination of strong client authentication and fine-grained authorization. Here’s how they complement each other: Dual Authentication and Authorization mTLS provides a strong, cryptographic client authentication mechanism, ensuring that only authorized clients (those with valid client certificates) can establish a connection. OAuth2 Client Credentials provides a token-based mechanism for authorizing the client’s access to specific APIs or resources. The access token contains information about the client’s permissions and access scope. Layered Security By using both mTLS and OAuth2, you establish multiple layers of security. Even if an access token is somehow obtained by an attacker, mTLS ensures that only clients with a valid certificate can connect. Conversely, even if a client possesses a valid certificate, it still needs a valid access token to access protected resources. Preventing Token Theft and Replay Attacks With mTLS, the secure communication channel prevents token theft during transmission. Even if a token were somehow intercepted, it would be useless without the client’s certificate to establish the connection. Enhanced Security for Sensitive Applications For highly sensitive applications, combining mTLS with OAuth2 Client Credentials ensures that only authenticated clients (validated by their certificates) and authorized clients (validated by their tokens) can access resources. This is particularly important in zero-trust environments or for internal microservices communication. Compliance and Regulatory Requirements Some industries require strong client authentication and end-to-end encryption. Combining mTLS with OAuth2 can help meet these regulatory requirements by ensuring secure communication and controlled access. Summary By combining mTLS with OAuth2 Client Credentials Grant, you gain the benefits of both strong client authentication and fine-grained access control, enhancing the overall security posture of your application. • [mTLS](https://developers.finqware.com/api-reference/security/mtls.md): mTLS is a mechanism for ensuring that both the client and server authenticate each other over a TLS connection. It is an extension of standard TLS (which typically only authenticates the server to the client). How mTLS Works Client Authentication: In addition to the server presenting its certificate, the client also presents its own certificate to the server. Certificate Verification: Both parties verify the certificates they receive. This ensures that both the client and server are who they claim to be, providing bidirectional authentication. Secure Communication: Once both parties are authenticated, a secure encrypted communication channel is established. Benefits of mTLS Strong, cryptographic client authentication. Prevents unauthorized clients from connecting to the server. Ensures data integrity and confidentiality during transmission. Setup Setting up mTLS requires two steps. Please contact us for: Enabling your API Client for mTLS Sharing your certificates in order to be added to our PKI infrastructure Certificate Requirements Certificates must use either RSA or ECDSA ciphers. For client (leaf) certificates: The BasicConstraints extension must not contain CA=true The ExtendedKeyUsage extension must contain clientAuth The ExtendedKeyUsage extension must not contain the codeSigning , timeStamping , or OCSPSigning fields The certificate must not be expired The client certificate cannot be a self-signed certificate For root and intermediate certificates: The BasicConstraints extension must contain CA=true The KeyUsage extension must be set to keyCertSign The ExtendedKeyUsage extension should contain the clientAuth field The certificate must not be expired • [OAuth2](https://developers.finqware.com/api-reference/security/oauth2.md): OAuth2 Client Credentials Grant is a method for obtaining access tokens that can be used to authenticate requests to an API. It is typically used when a client (such as a service or application) needs to access resources or APIs on behalf of itself, not on behalf of a user. How OAuth2 Client Credentials Grant Works The client (service or application) authenticates with the authorization server using its client ID and secret. If the credentials are valid, the authorization server issues an access token. The client uses this access token to authenticate its requests to the resource server (API). Benefits of OAuth2 Client Credentials Provides a mechanism for API clients to obtain access tokens for authenticating requests. Supports fine-grained authorization and scopes to control access to resources. Enables centralized management of client credentials and access policies. Private Key JWT Private Key JWT is a method of client authentication where the client creates and signs a JWT using its own private key. This method is described in a combination of RFC 7521 (Assertion Framework) and RFC 7523 (JWT Profile for Client Authentication), and referenced by OpenID Connect and FAPI 2.0 Security Profile. Although we support the Client Secret ( RFC 6749 ) authentication, we recommend Private Key JWT as it does not involve a process of sharing secrets. Setup Setting up OAuth2 requires a few steps. Please contact us for: Enabling your API Client for OAuth2 Sharing the public key which we’ll use to verify the signed requests to our Authorization server. Example script for generating the public/private key pair:#!/bin/bash # Generate private key in PEM format openssl genpkey -algorithm RSA -out private.key.pem -pkeyopt rsa_keygen_bits:2048 # Generate public key in PEM format (intermediate step) openssl rsa -pubout -in private.key.pem -out public.key.pem # Convert private key to JWK (JSON Web Key) format private_jwk=$(openssl rsa -in private.key.pem -noout -text | \ awk ' /modulus:/{p=1;next}/publicExponent:/{p=0}p' | \ tr -d ' \n:' | \ xxd -r -p | base64 -w 0 | \ tr '+/' '-_' | tr -d '=') private_exp=$(openssl rsa -in private.key.pem -noout -text | \ awk '/privateExponent:/{p=1;next}/prime1:/{p=0}p' | \ tr -d ' \n:' | \ xxd -r -p | base64 -w 0 | \ tr '+/' '-_' | tr -d '=') # Convert public key to JWK format modulus=$(openssl rsa -pubin -in public.key.pem -modulus -noout | \ cut -d'=' -f2 | \ xxd -r -p | base64 -w 0 | \ tr '+/' '-_' | tr -d '=') # Generate key ID (kid) kid=$(openssl rand -hex 32) # Create public key JWK echo "{ \"kty\": \"RSA\", \"kid\": \"$kid\", \"n\": \"$modulus\", \"e\": \"AQAB\", \"alg\": \"RS256\", \"use\": \"sig\" }" > public.key.json # Create private key JWK echo "{ \"kty\": \"RSA\", \"kid\": \"$kid\", \"n\": \"$modulus\", \"e\": \"AQAB\", \"d\": \"$private_exp\", \"alg\": \"RS256\", \"use\": \"sig\" }" > private.key.json echo "Keys generated successfully!" echo "Files created:" echo "- private.key.pem (Private key in PEM format)" echo "- private.key.json (Private key in JWK format)" echo "- public.key.json (Public key in JWK format)" # Display the generated kid for reference echo -e "\nKey ID (kid) for reference:" echo "$kid" Getting an Access Token Making requests to the Link API in production requires a valid Bearer access token, sent via the standard Authorization header. The process below describes the way to acquire an access token. Example script: Sh #!/bin/bash # Your API client id CLIENT_ID="0o....17" # The /token endpoint AUD="https://finqware.okta.com/oauth2/ausfqbxutkZBUKUgQ417/v1/token" # The key id (kid) of your key KID="t4cs...j3s" # Your private key in PEM format PRIVATE_KEY_PATH="./private.key.pem" # Generate timestamps iat=$(date +%s) exp=$((iat + 3600)) # Create JWT header (Base64URL-encoded) HEADER=$(echo -n '{"alg":"RS256","typ":"JWT","kid":"'"$KID"'"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=') # Create JWT payload (Base64URL-encoded) PAYLOAD=$(echo -n '{"aud":"'"$AUD"'","iss":"'"$CLIENT_ID"'","sub":"'"$CLIENT_ID"'","iat":'"$iat"',"exp":'"$exp"',"jti":"'"$(uuidgen)"'"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=') # Combine header and payload DATA="$HEADER.$PAYLOAD" # Sign the JWT using RS256 SIGNATURE=$(echo -n "$DATA" | openssl dgst -sha256 -binary -sign "$PRIVATE_KEY_PATH" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=') # Final JWT (signed client_assertion) JWT="$DATA.$SIGNATURE" echo "Generated JWT (signed client_assertion):" echo "$JWT" echo -e "\n" # Create the curl command with the generated JWT echo -e "\nCurl command:" echo "curl --location --request POST '$AUD' \\ --header 'Accept: application/json' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'client_id=$CLIENT_ID' \\ --data-urlencode 'grant_type=client_credentials' \\ --data-urlencode 'scope=pay_by_link' \\ --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \\ --data-urlencode 'client_assertion=$JWT'" echo -e "\n" echo -e "\nRetrieving the authz Bearer token..." curl --location --request POST "$AUD" \ --header 'Accept: application/json' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode "client_id=$CLIENT_ID" \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'scope=pay_by_link' \ --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \ --data-urlencode "client_assertion=$JWT" Your backend is responsible to implement a mechanism for keeping an up-to-date access-token available at all times. There are mature libraries for implementing this process, available in all mainstream programming languages (e.g., Java , NodeJS ). Step 1: Build the Client Assertion JWT Build a token with a payload such as below and sign it with your private key. The signed token is called a client_assertion in OAuth2 terms. The example below assumes your client_id is xyz123abc and key id ( kid ): a1b2c3 : JSON Header (must specify your key id): JSON { "alg": "RS256", "typ": "JWT", "kid": "a1b2c3" } JSON Payload: JSON { "aud": "https://finqware.okta.com/oauth2/ausfqbxutkZBUKUgQ417/v1/token", "iss": "xyz123abc", "sub": "xyz123abc", "iat": 1741161292, "exp": 1741164892, "jti": "9CF1E...479C" } Step 2: Request Access Token Use the client_assertion computed above to make a call to our /token endpoint in order to get an access-token: Bash curl --location --request POST 'https://finqware.okta.com/oauth2/ausfqbxutkZBUKUgQ417/v1/token' \ --header 'Accept: application/json' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'client_id=xyz123abc' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'scope=pay_by_link' \ --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \ --data-urlencode 'client_assertion=eyJhbGciOiJSUzI1NiIsIn....le3qGb5mp-yUmPqUwoyZaA9g' Step 3: Use the Access Token Use the received access-token for making calls to the Link API until its expiration (each access-token is valid for a limited time). Include the token in the Authorization header: Authorization: Bearer your_access_token • [Webhook signing and callbacks](https://developers.finqware.com/api-reference/security/webhook-signing-and-callbacks.md): Webhook requests (payment status, consent status, job status) are signed so you can verify they come from FinqLink. You can also restrict incoming requests to our callback IPs. Headers Header Description x-signature JWS compact string (header.payload.signature, Base64URL). The signed payload is the raw JSON body of the request. x-signature-kid Key ID of the key used to sign; use it to select the key from the JWKS for verification. How to verify Fetch the public keys: GET {base_url}/.well-known/jwks.json (use your environment base URL). Response shape: {"keys": [ { "kty", "kid", "alg", "use", "n", "e" }, ... ]} . From the webhook request: read the x-signature-kid and x-signature headers and the raw request body (UTF-8 JSON). Find the key in keys with matching kid . Verify the JWS in x-signature : the JWS payload must equal the raw body, and the signature must verify with that key (RS256 or ES256 per key’s alg ). Reject if kid is unknown, signature is invalid, or payload does not match body. You can implement this with standard JWS/JWK libraries in any language (e.g. jose in Node.js, JOSE in Elixir). Key rotation policy Signing keys are rotated automatically at a regular interval. The current key is used to sign new webhook requests and remains in use for approximately 30 days until the next rotation. When a new key is introduced, the previous key stays published in JWKS so you can continue to verify webhooks that were signed with it (for example, requests sent just before or during the rotation). The previous key remains available in JWKS for approximately 30 days after it is replaced. After that, it is removed from JWKS and webhooks signed with it can no longer be verified—treat any webhook whose x-signature-kid is not present in JWKS as invalid. JWKS endpoint and key versions GET /.well-known/jwks.json returns the public keys you need to verify webhook signatures. The endpoint always lists exactly two keys: the current key (used for new webhooks) and the previous key (used for webhooks sent before the latest rotation). Keys are ordered newest first. Use x-signature-kid from each webhook to pick the right key for verification. If you receive a webhook with a kid that is not in the JWKS response, do not trust it (it may be a replay or from an outdated integration). JavaScript verification example (Express + jose) This example uses Express with a raw body parser and the jose library to verify the webhook signature against the remote JWKS. The signed payload must match the raw request body byte-for-byte, so do not use express.json() for the webhook route—use express.raw() . Javascript import express from "express"; import { compactVerify, createRemoteJWKSet } from "jose"; const app = express(); // Capture raw body as Buffer app.use(express.raw({ type: "application/json" })); const BASE_URL = process.env.FINQWARE_BASE_URL; // e.g. https://sandbox-pay.finqware.com const JWKS = createRemoteJWKSet(new URL(`${BASE_URL}/.well-known/jwks.json`)); app.post("/webhook", async (req, res) => { try { const sig = req.header("x-signature"); const kidHeader = req.header("x-signature-kid"); if (!sig || !kidHeader) return res.sendStatus(401); // Verify signature (jose picks key by kid from the JWS header) const { payload, protectedHeader } = await compactVerify(sig, JWKS); // Optional defense-in-depth: compare kid values if (protectedHeader?.kid && protectedHeader.kid !== kidHeader) { return res.sendStatus(401); } // Payload must match raw body exactly const rawBody = req.body; // Buffer from express.raw if (Buffer.compare(Buffer.from(payload), rawBody) !== 0) { return res.sendStatus(401); } // At this point: signature valid + body matches // Now you can JSON.parse(rawBody.toString("utf8")) safely res.sendStatus(200); } catch (e) { res.sendStatus(401); } }); app.listen(3000); Callbacks from fixed IPs You can restrict your webhook endpoint to accept requests only from FinqLink’s outbound IPs: Environment Outbound IP Test 34.89.170.122 Production 34.159.239.125 Use firewall or load-balancer rules to allow only these source IPs for the path that receives webhooks. • [Pay APIs](https://developers.finqware.com/api-reference/pay-apis.md): Payment initiation and provider discovery endpoints. Overview FinqLink is a set of APIs for account-to-account payments/transfers through open-banking and other local/custom integrations (eg: RoPay in Romania). The platform enables API clients to create payment links that allow end-users to complete payments through their banking providers using Strong Customer Authentication (SCA). Pay-by-link is a method that breaks the payment process in two distinct phases: the creation of a payment request, operated by the creditor (receiver of funds) the acceptance & authorization of the payment, operated by the debtor (the source of funds) The payment request encapsulates metadata such as: amount, currency, the list of goods to be acquired etc. Once its created, the payment request is wrapped into a transportable object - aka the link- such as a URL or a QR code. The link is sent to a debtor who will only check/approve & authorize the payment. Payment providers A payment-provider is a partner institution that operates payment services. FinqLink integrates with these providers over APIs such as open-banking payment initiation APIs. Each provider has a unique code. Eg: rzb_ro , cec_ro etc. A provider may have one or multiple payment-methods offering different capabilities (domestic-only transfers, corporate-only transfers etc) we provide an API and a dashboard for quering and visualising all the details regarding providers & methods. Payment Flow Types The API supports multiple payment flow types: link : Default web-based payment experience via FinqLink WebUI wrapped_sca : SCA URLs wrapped in a transportable link operated via FinqLink WebUI direct_sca : Mobile app-to-app experience with direct bank redirect (requires a custom eIDAS certificates setup) redirect_sca : Mobile app-to-app experience with redirect via FinqLink WebUI The FinqLink WebUI The WebUI is a web application that facilitates the payment process by providing a user interface for the end-user to complete the payment. It comes with a payment-method selection component, payment details and real-time status updates. Webhooks The API supports webhook notifications for payment status updates. Configure webhook URLs when creating payment links. Webhook payloads include: type : Event type — always "payment_status_update" for payment links link_id : The payment link UUID status : New payment status Decimal Values Monetary amounts are represented as strings to maintain precision (e.g., “100.50”). No leading zeros allowed (except for values less than 1, e.g., “0.50”) No comma separators allowed Decimal point is optional for whole amounts • [Links](https://developers.finqware.com/api-reference/pay-apis/links.md): Create, retrieve, and manage payment links for open-banking transactions • [Create Link](https://developers.finqware.com/api-reference/pay-apis/links/create-link.md): Creates a new payment link for initiating a bank transfer through open-banking. Returns a web URL where the end-user can complete the payment through their bank’s Strong Customer Authentication (SCA) flow. Payment Flow Types The type option determines how the payment link is created and the user experience: Type Behavior Use Case link Returns a transportable payment link, end-user opens it in [FinqLink WebUI](api-reference/pay-apis#The-FinqLink-Pay-WebUI) to complete the payment. Offers maximum flexibility in terms of expiration and user optionality. Use this flow when generating payment links expected to be operated after a longer time. Example: an invoice sent over email which you don't expect an immediate action for. Invoicing, QR codes direct_sca A non-transportable payment link. The API returns a native authorisation URL received from the payment provider and your application will process the redirect call from the payment provider. Available under certain custom requirements (discuss with a Finqware representative). Mobile app-to-app experience wrapped_sca A transportable payment link for immediate usage. The authorisation URL is requested at link creation, hence there is no optionality anymore for the user to choose a different payment provider. Use this flow when (1) you know upfront all the payment details and (2) you expect immediate action from your user, as the authorisation URL may expire in minutes. E-commerce, invoicing redirect_sca Similar to direct_sca, but handles redirects through WebUI App-to-app UX Payment Method Selection Use the payment_method object as a filter to restrict the available payment methods: Filter by specific banks ( provider_id ) Filter by account type ( remitter_type : retail and/or corporate) Filter by payment rails ( payment_scheme : instant, domestic, SEPA) Filter by environment ( env : sandbox, stage, prod) The WebUI selector component will only show the payment methods that match the filter. Example if you want to restrict your user to pay from their personal account from a list of specific banks: JSON { "payment_method": { "provider_id": ["bt_ro", "ing_ro", "bcr_ro"], "remitter_type": ["retail"], "env": "prod" } } External provider errors For direct_sca , wrapped_sca , and redirect_sca flows, the payment intent is submitted synchronously to the bank during link creation. If the middleware HTTP call fails (timeout, connection refused, DNS, etc.), the response will be HTTP 400 with code external_api_unavailable instead of a gateway timeout — clients can pattern-match on the code and retry. • [Get Link](https://developers.finqware.com/api-reference/pay-apis/links/get-link.md): Retrieves detailed information about a specific payment link. Returns the current status, expiration, selected payment method, and service provider details. Response Fields status : Current payment status (see LinkStatus enum for possible values) is_expired : Whether the link has expired payment_method : Details of the selected payment method (if user has selected one) service_provider : Details of the selected bank (if user has selected one) • [List Links](https://developers.finqware.com/api-reference/pay-apis/links/list-links.md): Retrieves payment links owned by the authenticated API client with optional filtering and pagination. Returns a summary of each link including status, expiration, and web URL. Note : Only returns links created by the authenticated API client. Filtering Use the filter object to narrow down links by: status : Filter by payment status (created, completed, failed, etc.) inserted_at_from / inserted_at_to : Filter by creation date range Pagination Uses keyset-based pagination for efficient traversal of large result sets. Use the keyset value from the last link in the current page as the after parameter in your next request to fetch the next page. • [Handle Redirect](https://developers.finqware.com/api-reference/pay-apis/links/handle-redirect.md): Handles the callback redirect from the bank’s SCA authentication flow. Used only for direct_sca payment flows where the bank redirects back to your provided endpoint (custom setup with each bank required). Execution Modes Async (default) : Returns immediately with status redirect_in_progress Sync : Waits for final payment status (completed, failed, or submitted) Response Status Codes 200 : Redirect processed successfully 201 : Redirect already processed (idempotent retry) 202 : Redirect in progress (async mode or concurrent request) Note : This endpoint is available for selected customers only (licensed entities). • [Providers](https://developers.finqware.com/api-reference/pay-apis/providers.md): Discover available banks and payment methods for payment initiation. Payment provider discovery endpoints for querying available banks and payment methods. Use these endpoints to discover which banks are available for payment initiation, their capabilities, and validation schemas for payment intents. Filtering Filter providers by country code (e.g., “ro” for Romania) Filter by specific provider identifiers Payment Methods Each provider may have multiple payment methods with different: Account types (retail/corporate) Payment schemes (instant, domestic, SEPA) Environment availability (sandbox, stage, prod) Validation Schemas Request validation schemas to ensure payment intents meet each bank’s requirements. • [List Providers](https://developers.finqware.com/api-reference/pay-apis/providers/list-providers.md): Retrieves a list of available payment service providers (banks) and their payment methods. Use this endpoint to discover which banks are available for payment initiation. Filtering Use the filter object to narrow down providers by: country : Filter by country code (e.g., “ro” for Romania) public_name : Filter by specific provider identifiers Payment Methods Set options.show_payment_methods: true to include detailed payment method information. Use options.payment_methods_filter to further filter payment methods by: remitter_type : retail or corporate accounts payment_scheme : payment rails (ro domestic, ro instant, sepa, sepa_instant) interface_type : backend API type interface_env : environment (sandbox, stage, prod) Validation Schemas Set options.show_validation_schema: true to include JSON schemas for validating payment intents against each payment method’s requirements. Method access restrictions An API client may be restricted to a subset of methods. In that case the response only includes methods the client is allowed to use, and providers left with no accessible method are omitted from the list. If the request matches methods that are all outside the client’s allow-list, the endpoint returns 400 instead of an empty list. Set options.show_subscribed_methods: false to browse the full catalog as an informative tool, ignoring the client’s method-access restrictions. • [Get Provider](https://developers.finqware.com/api-reference/pay-apis/providers/get-provider.md): Retrieves detailed information about a specific payment service provider (bank). Returns provider metadata and optionally its available payment methods. Payment Methods Set options.show_payment_methods: true to include payment method details. Each payment method includes: Supported account types (retail/corporate) Payment scheme (instant, domestic, SEPA) Environment availability Feature capabilities Validation Schema Set options.show_validation_schema: true to include the JSON schema for validating payment intents for each payment method. Method access restrictions An API client may be restricted to a subset of methods. The response only includes methods the client is allowed to use. If the client has no accessible method on the requested provider, the endpoint returns 400 . Set options.show_subscribed_methods: false to browse the full catalog as an informative tool, ignoring the client’s method-access restrictions. • [Data APIs](https://developers.finqware.com/api-reference/data-apis.md): Account Information Services (AIS) endpoints for accessing banking data. Note: This API is in public beta and may be slightly changed based on your feedback. Webhooks are supported for: Consent status updates : Notified when consent status changes (e.g., started → active ) Job status updates : Notified when data refresh jobs complete or change status Banking data retrieval endpoints for accounts, balances, and transactions. Pagination The transactions and balances list endpoints use keyset-based pagination. Use the keyset value from the last record as the after parameter in your next request to fetch the next page. Filtering All data endpoints support filtering by various criteria: Accounts: currency, account type Balances: currency, type, account ID Transactions: amount range, date range, credit/debit indicator, status Balance Types Check the balance types documentation for more details. • [Consents](https://developers.finqware.com/api-reference/data-apis/consents.md): Manage user consents for accessing account information. AIS consent management endpoints for accessing banking account information. Overview Account Information Services (AIS) allows authorized access to banking data including accounts, balances, and transactions. Users must authorize access through their bank’s Strong Customer Authentication (SCA) flow. Consent Scope When creating a consent, you can specify which types of data you want to access: Scope Description ["accounts", "balances", "transactions"] Full access (default) - includes transaction history ["accounts", "balances"] Accounts and balances only - faster job completion Note: Other scope combinations are not supported. If no scope is provided, full scope is assumed. Consent Lifecycle Create consent with desired scope (accounts, balances, or full) User authorizes via bank’s SCA flow Consent becomes active for data access Use data endpoints to retrieve banking information Refresh data as needed using background jobs Consent Statuses Status Description created Consent created, not yet accessed started User accessed consent link sca url retrieved Bank SCA URL obtained awaiting decoupled authz Waiting for user authorization in the banking app (decoupled flow) awaiting_authz Waiting for user authorization authorized User authorized, processing active Consent active, data accessible expired Authorization link timed out (user can no longer access WebUI) revoked Data access explicitly withdrawn via API (/ais/consents/revoke) deactivated Consent validity period ended (authorized_until reached) - automatic failed Authorization failed suspended Consent temporarily suspended Understanding Expiration vs Revocation There are two different time-based concepts for consents: Concept Field Description Link Expiration expires at (from expires in) When the authorization link/URL becomes inaccessible. After this time, users cannot access the WebUI to complete bank authorization. Max 45 days. Consent Validity authorized until (from consent validity_days) When the data access consent expires and is automatically deactivated. After this time, data retrieval is no longer possible. Max 180 days. Expired : The authorization link has timed out - only affects the ability to complete the SCA flow Revoked : The data access consent has been explicitly terminated via the /ais/consents/revoke API endpoint (manual/client-driven) Deactivated : The consent validity period has ended ( authorized_until reached) - automatic/system-driven, no more access to banking data Webhooks Configure webhook_url when creating consents to receive notifications on status changes. Webhook Payload: JSON { "type": "consent_status_update", "consent_id": "123e4567-e89b-12d3-a456-426614174000", "status": "active" } Field Type Description type string Always consent status update consent_id uuid The consent that was updated status string New consent status (see statuses above) • [Create Consent](https://developers.finqware.com/api-reference/data-apis/consents/create-consent.md): Creates a new AIS consent for accessing banking account information. Returns a web URL where the end-user can authenticate with their bank and authorize access. The consent can be configured with various options including: Scope of data access (accounts, balances, transactions) Consent validity period Provider filtering Webhook notifications Custom redirect URLs Decoupled AIS methods Some AIS methods (e.g. BRD) use a decoupled authorization flow: the end user authorises the consent in their banking mobile app instead of being redirected to a bank page. For direct_sca / redirect_sca consents resolved to such a method, the response contains web_url: null and a message field with the instruction to display to the user. Track the authorization outcome via status webhooks ( awaiting_decoupled_authz → authorized → active ) or /ais/consents/get . External provider errors For direct_sca , wrapped_sca , and redirect_sca flows, the consent is initialized synchronously with the bank during creation. Middleware-side failures may surface as: external_api_unavailable (HTTP 400) — middleware HTTP timeout / connection error external_api_error (HTTP 400) — provider returned a structured error during the SCA / pre-SCA step (message format: Provider error: <middleware message> ) • [Get Consent](https://developers.finqware.com/api-reference/data-apis/consents/get-consent.md): Retrieves detailed information about an existing AIS consent, including: Current status (created, completed, failed, etc.) Associated accounts (if consent is completed) Service provider information Expiration details This endpoint returns successfully for any existing consent, regardless of its current status (e.g. created , active , revoked , deactivated , expired , failed ). • [Revoke Consent](https://developers.finqware.com/api-reference/data-apis/consents/revoke-consent.md): Revokes an existing AIS consent by setting its status to revoked . If the consent is already revoked , this endpoint is idempotent and returns 200 . If the consent status is expired , deactivated , failed , or suspended , this endpoint returns 400 with code consent_not_active . • [Handle Redirect](https://developers.finqware.com/api-reference/data-apis/consents/handle-redirect-1.md): Handles the callback redirect from the bank’s SCA authentication flow for AIS consents. Used only for direct_sca consent flows where the bank redirects back to your provided endpoint (custom setup with each bank required). Execution Modes Async (default) : Returns immediately with status redirect_in_progress Sync : Waits for consent to reach a final status (active, failed, authorized) Response Status Codes 200 : Redirect processed successfully 201 : Redirect already processed (idempotent retry) 202 : Redirect in progress (async mode or concurrent request) Note : This endpoint is available for selected customers only (licensed entities). • [Data](https://developers.finqware.com/api-reference/data-apis/data.md): Retrieve account information including accounts, transactions, and balances • [List Accounts](https://developers.finqware.com/api-reference/data-apis/data/list-accounts.md): Retrieves a list of bank accounts associated with a consent, with optional filtering. Each account includes the latest balances from the most recent data refresh job. Consent status : If the consent is expired , revoked , deactivated , failed , or suspended , this endpoint returns 400 with code consent_not_active . Filtering Accounts can be filtered by: Currency Account type (e.g., “Personal current account”) Account sub-type (e.g., “CurrentAccount”) • [List Transactions](https://developers.finqware.com/api-reference/data-apis/data/list-transactions.md): Retrieves a list of bank transactions with optional filtering and keyset-based pagination. Consent status : If the consent is expired , revoked , deactivated , failed , or suspended , this endpoint returns 400 with code consent_not_active . Pagination Use the keyset value from the last transaction in the current page as the after parameter in your next request to fetch the next page. The pagination.more? field indicates if more records are available. Sort Order Transactions are returned sorted by booking_date_time descending (most recent first), then by inserted_at descending within the same booking date, then by id descending as a tiebreaker for keyset pagination. Transactions without a booking date appear last. Note on booking_date_time granularity: Most European banks integrated via FinqLink expose PSD2 APIs based on the Berlin Group standard, which only provides transaction booking information as a calendar date (no time-of-day). FinqLink normalizes this into a full timestamp with the time set to 00:00:00Z . In practice, many transactions on the same day share the same midnight timestamp; their relative order is determined by inserted_at descending. booking_date_from / booking_date_to effectively filter by calendar day — always pass values aligned to T00:00:00Z . Any other time-of-day (e.g. 2026-04-17T12:00:00Z ) will silently exclude that entire day. For intra-day filtering (e.g. “transactions that appeared after a specific time today”) use inserted_from / inserted_to instead; they support full time-of-day resolution. The real granularity depends on how often data is refreshed for the consent. Filtering Transactions can be filtered by: Amount range (min/max) Currency Booking date range Account ID Credit/debit indicator Transaction status • [List Balances](https://developers.finqware.com/api-reference/data-apis/data/list-balances.md): Retrieves a history of account balances associated with a consent, with optional filtering. For the most recent balance only, please check the accounts/list endpoint. Consent status : If the consent is expired , revoked , deactivated , failed , or suspended , this endpoint returns 400 with code consent_not_active . Important Notes At least one normalized balance type ( available ) is always provided per account The amount field is always a positive number - use credit_debit_indicator to determine the actual sign For overdraft/negative balances, credit_debit_indicator will be debit Normalized Balance Types These types are commonly available across banks: Type Description available Available balance calculated in the course of the business day, at the time specified, subject to further changes. Calculated on booked credit/debit items. closing Closing balance of cleared amount. Only provided when bank explicitly provides ClosingCleared/Booked balance. Additional Bank-Specific Balance Types Type Description closing_available Closing balance at account owner's disposal on the date specified closing_booked Balance at end of pre-agreed account reporting period (sum of opening booked + all entries during period) closing_cleared Closing balance of cleared amount on date specified expected Balance of booked entries and pending items, projecting end-of-day balance if everything is booked forward_available Forward available balance at disposal on date specified information Balance for informational purposes interim_available Available balance in course of business day, subject to changes interim_booked Balance calculated in course of business day, subject to changes interim_cleared Cleared balance in course of business day, subject to changes opening_available Opening balance at account owner's disposal on date specified opening_booked Book balance at beginning of reporting period (equals previous closing book balance) opening_cleared Opening balance of cleared amount on date specified previously closed booked Balance at previously closed reporting period Balance Interpretation Guide The meaning of a balance depends on the combination of type , credit_limit_included , and credit_debit_indicator : Available Balance credit_limit_included credit_debit_indicator Meaning false credit Account balance representing the amount of money which can be spent false debit Borrowed funds from the account's associated overdraft true credit Total balance = account balance + overdraft value Closing Balance credit_limit_included credit_debit_indicator Meaning false credit Account balance at the official banking day closing false debit Borrowed funds from overdraft at banking day closing true credit Remaining unused overdraft amount at day closing • [Jobs](https://developers.finqware.com/api-reference/data-apis/jobs.md): Schedule and monitor background data refresh operations. Background data refresh job management for AIS. Purpose After initial consent authorization, use jobs to refresh banking data on demand. Jobs fetch the latest accounts, balances, and transactions from the banking provider. Scope-Based Job Behavior Job execution varies based on the consent’s scope: Full scope ( [accounts, balances, transactions] ): Job fetches all data types including transaction history Accounts/balances only ( [accounts, balances] ): Job completes faster by skipping transaction fetching For consents with [accounts, balances] scope, jobs will transition directly from balances_ready to job_completed . Cooldown Period A cooldown period is enforced between refresh requests to prevent excessive API calls to banking providers. If you attempt to create a job during the cooldown period, you’ll receive a 400 error with code cooldown_failed . Job Statuses Status Description job_started Job created and queued for processing accounts_ready Accounts fetched and stored balances_ready Balances fetched and stored transactions_fetching Transactions fetching in progress (skipped for accounts/balances scope) job partially completed Some data fetched successfully job_completed All data fetched successfully job_failed Job failed due to an error Webhooks Provide a webhook_url when creating a job to receive notifications on status changes. Webhook Payload: JSON { "type": "job_status_update", "consent_id": "123e4567-e89b-12d3-a456-426614174000", "job_id": "job-uuid-456", "status": "job_completed" } Field Type Description type string Always job status update consent_id uuid The consent associated with this job job_id uuid The job that was updated status string New job status (see statuses above) • [Create Data Refresh Job](https://developers.finqware.com/api-reference/data-apis/jobs/create-data-refresh-job.md): Initiates a background job to refresh AIS data (accounts, balances, transactions) from the banking provider. Consent status : The consent must be active . Otherwise, this endpoint returns 400 with code consent_not_active . Cooldown Period To prevent excessive API calls to banking providers, a cooldown period is enforced between refresh requests. If you attempt to create a job during the cooldown period, you’ll receive a 400 error with code cooldown_failed . Concurrent jobs Only one data-refresh job can run per consent at a time. If another job is still in progress, this endpoint returns 400 with code job_in_progress . Callback URL You can optionally provide a callback URL to receive a notification when the job completes. • [Get Data Refresh Job](https://developers.finqware.com/api-reference/data-apis/jobs/get-data-refresh-job.md): Gets the current status and details of a data refresh job. Consent status : If the consent is expired , revoked , deactivated , failed , or suspended , this endpoint returns 400 with code consent_not_active . Job Statuses job_started : Job created accounts_ready : Accounts fetched and stored in the database balances_ready : Balances fetched and stored in the database transactions_fetching : Transactions fetching has started job_partially_completed : Job completed partially (some data was fetched and stored) job_completed : Job completed successfully job_failed : Job failed (no data was fetched and stored)