Business Banking API documentation

Download OpenAPI specification:Download

Authorization

We use cryptographic signature to authorize API requests.
To configure your API keys for selected entity please login to our banking app Developer Section.
You have to configure your whitelisted IPs and public key which will be used for request signature verification.
Do not share your private key with anybody. We never asks you for private key.

API HOSTNAME

Please note that we use api.narvi.com fully qualified domain to interact with your integration. All your api requests should use this domain to communicate with our REST API.

Request Authorization

Each request needs to have the following headers:
- API-KEY-ID - api key id gathered from configured api key Developer Section
- API-REQUEST-ID - valid UUID or timestamp, can't be duplicated across requests
- API-REQUEST-SIGNATURE - request signature

API-REQUEST-ID (Request ID)
- valid UUID or timestamp,
- it can't be duplicated across requests

API-REQUEST-SIGNATURE (Request signature)
Request signature is the signature of sha256 of the concatenated following items (request descriptor)
- the absolute request url without query params (e.g. http://api.narvi.com/rest/v1.0/transactions/create)
- the uppercase request method (e.g. POST, GET, PUT, DELETE)
- request ID - valid UUID, can't be duplicated across requests
- query params encoded in JSON canonical form - RFC 7159 JSON (The order of JSON key-value pairs is very important. Please double-check that it is in the correct canonical form. All query parameters keys and values must have the string type. Use an empty string instead if there are no query parameters).
- payload encoded in JSON canonical form - RFC 7159 JSON (The order of JSON key-value pairs is very important. Please double-check that it is in the correct canonical form. Use an empty string instead if there is no payload).
- if payload contains file object use sha256 of the file content to create payload canonical form for request descriptor

Signature example
For GET request https://api.narvi.com/?account_pid=KFGKJ5L27ASGTZAO&kind=CREDIT the signature should be created as follow:
- generate a request ID: e.g. da43520e-800b-41c5-a4a9-7287a64c87fa (valid UUID, can't be duplicated across requests)
- generate request descriptor: https://api.narvi.com/rest/v1.0/transactions/listGET1693416230449{"\account_pid":"KFGKJ5L27ASGTZAO","kind":"CREDIT"}
- generate sha256 of the request descriptor
- generate signature with hashing algorithm sha256 of the generated sha256 above
- encode the signature with base64

For POST request https://api.narvi.com/rest/v1.0/transactions/create with the payload
{"account_pid": "KFGKJ5L27ASGTZAO" ,"recipient": {"name": "John Doe", "number": "FI8379600186405354" ,"bic": "NARIFXX", "country": "FI"}, "currency": "EUR","amount": 100, "remittance_information":{"ustrd": "test transfer"}}
the signature should be created as follow:
- generate a request ID: e.g. da43520e-800b-41c5-a4a9-7287a64c87fa (valid UUID, can't be duplicated across requests)
- generate request descriptor: https://api.narvi.com/rest/v1.0/transactions/createPOST1693416796324{"account_pid":"KFGKJ5L27ASGTZAO","amount":"100","currency":"EUR","recipient":{"bic":"NARIFXX","country":"FI","name":"John Doe","number":"FI8379600186405354"},"remittance_information":{"ustrd":"test transfer"}}
- generate sha256 of the request descriptor
- generate signature with hashing algorithm sha256 of the generated sha256 above
- encode the signature with base64

Webhooks

To enable webhooks, please login to Developer Section and configure webhook endpoints for selected entity. After you enable them, we will push real-time event data to your application's webhook endpoint when events happen in your banking account. We use HTTPS to send webhook events to your app as a JSON payload that includes an Event object.

Webhooks IPs

The full list of IP addresses that api.narvi.com may resolve to is:
3.76.153.24

Delivery behaviours

We attempt to deliver the event to your webhook endpoint for up to 3 days with an exponential back off. In the log section of the Dashboard, you can view when the next retry will occur. If your endpoint has been disabled or deleted when we attempt a retry, future retries are cancelled.

Your endpoint must quickly return a successful status code (2xx) prior to any complex logic that could cause a timeout. For example, you must return a 200 response before updating a customer’s balance.

Delivery headers

HTTP payloads that are delivered to your webhook's configured URL endpoint will contain several special headers:
- USER-AGENT - always equal 'webhook'
- WEBHOOK-REQUEST-TIMESTAMP - timestamp in millisecond when webhook action occured
- WEBHOOK-REQUEST-EVENT-TYPE - the event type
- WEBHOOK-REQUEST-EVENT-PID - event public id
- WEBHOOK-REQUEST-SIGNATURE - This is the sha256 hex digest of the request body and parameters

Webhook signature

Webhook signature must be checked by integrated application before processing the webhook data.
Webhook signature is the sha256 hex digest of the concatenated following items (request descriptor)
- the absolute webhook endpoint without query params (e.g. https://example.com/webhook/handler)
- the uppercase request method (e.g. POST, GET, PUT, DELETE)
- current timestamp in microseconds (taken from request header WEBHOOK-REQUEST-TIMESTAMP)
- event type (taken from request header WEBHOOK-REQUEST-EVENT-TYPE)
- event public id (taken from request header WEBHOOK-REQUEST-EVENT-PID)
- query params encoded in JSON canonical form - RFC 7159 JSON (The order of JSON key-value pairs is very important. Please double-check that it is in the correct canonical form. All query parameters keys and values must have the string type. Use an empty string instead if there are no query parameters).
- payload encoded in JSON canonical form - RFC 7159 JSON (The order of JSON key-value pairs is very important. Please double-check that it is in the correct canonical form. Use an empty string instead if there is no payload).
- webhook secret taken from developer panel

VOP Webhook Response & Signature

Verification of Payee (VOP) is a mechanism that checks if the recipient's name on a SEPA transfer matches the details held by the recipient's bank. This helps prevent payment fraud and misdirected payments by verifying the account holder's name before the transaction is processed.

The VOP scheme and its technical specifications are defined by the European Payments Council (EPC). The official scheme documentation can be found here: Verification Of Payee Scheme Inter-PSP API Specifications.

VOP Transaction Flow

When you initiate a SEPA transaction (e.g., via POST https://api.narvi.com/rest/v1.0/transactions/create), a VOP check is performed. Transaction object now has vop field which contains the result of the check:

  • null: VOP was not applicable to this transaction (e.g., non-SEPA transfers).
  • Object: When VOP is applicable, the object contains:
    • match_type (required): One of the following values:
      • "MTCH": (Match) The recipient name exactly matches the bank's records.
      • "NMTC": (No Match) The recipient name does not match.
      • "CMTC": (Close Match) The recipient name is similar but not identical.
      • "NOAP": (Not Applicable) VOP could not be performed by the recipient's bank.
    • recipient_matching_name (optional): For CMTC status, this field may contain the suggested correct recipient name from the bank's records.

Example vop object:

{
  "vop": {
    "match_type": "CMTC",
    "recipient_matching_name": "John Smith"
  }
}

If the result is a perfect match ("MTCH"), the transaction proceeds to CONFIRMED status as normal.

However, if the VOP result is not a match ("NMTC", "CMTC", or "NOAP"), the flow is interrupted and requires your action:

  1. The transaction is created with a CREATED status (not CONFIRMED).
  2. The transaction will not be processed until it is confirmed or canceled.
  3. A vop.created webhook event is sent to your configured endpoint.
  4. Your system must then approve or reject the transaction using one of two methods described below.

This is the primary method for handling VOP-pending transactions. You must respond directly to the webhook request with a 200 OK status and a specific, signed JSON body.

Configuration

To use this method, you must first upload your public key in the Developer Section. We will use this key to verify the signature of your response.

Note: This is different from the standard webhook signature verification.

  • You verify our incoming webhooks using the WEBHOOK-REQUEST-SIGNATURE header and your Webhook Secret.
  • You sign your response to the vop.created webhook using your private key.
Response Body

Your response must be a JSON object containing accept_vop, nonce, and signature.

  • accept_vop (boolean): true to accept the VOP findings and proceed with the transaction. false to cancel the transaction.
  • nonce (string): A unique identifier for this response (e.g., a timestamp or UUID) to prevent replay attacks.
  • signature (string): The Base64-encoded RSA-SHA256 signature.

Important: If your response body is empty, improperly formatted, or has an invalid signature, it will be ignored. The transaction will remain in CREATED status.

Response Signature Generation

To generate the signature:

  1. Create the JSON payload without the signature field:
    {
      "accept_vop": true,
      "nonce": "1678886400000"
    }
    
  2. Convert this object to its canonical JSON string representation (RFC 7159, keys sorted alphabetically).
  3. Generate a SHA-256 hash of the canonical JSON string.
  4. Sign the resulting hash using your private key with the RSA-SHA256 algorithm.
  5. Base64-encode the binary signature.
  6. Add this Base64-encoded string as the signature value to your JSON payload.

Final JSON Response Body:

{
  "accept_vop": true,
  "nonce": "1678886400000",
  "signature": "YOUR_BASE64_ENCODED_SIGNATURE_HERE"
}

Method 2: Use the Update Transaction API Endpoint

As an alternative, or if your webhook response fails, you can programmatically approve or reject the transaction by calling:

PATCH /rest/v1.0/transactions/update/{pid}

This endpoint uses standard API authentication (as described in the Authorization tag).

To confirm or cancel the transaction, send the following payload:

{
  "accept_vop": true
}
  • accept_vop (boolean): true to approve, false to cancel.
  • This operation is only valid while the transaction is in the CREATED status.

Accounts

Retrieve Account Details

Retrieves Account details

path Parameters
pid
required
string

A unique value identifying this sepa account.

Responses

Response samples

Content type
application/json
{
  • "pid": "KFGKJ5L27ASGTZAO",
  • "number": "FI2279600000000000",
  • "balance": 9997246,
  • "currency": "EUR",
  • "name": "EUR Account",
  • "kind": "PRIVATE"
}

List User Accounts

Returns paginated list of user accounts.

query Parameters
cursor
string

The pagination cursor value.

Responses

Response samples

Content type
application/json
{
  • "next": "string",
  • "previous": "string",
  • "results": [
    ]
}

Transactions

Create Transaction

Create User Transaction. If the transaction is for a SEPA payment and results in a Verification of Payee (VOP) status other than 'MTCH', the transaction will be created with a 'CREATED' status and await confirmation via the vop.created webhook or the PATCH /rest/v1.0/transactions/update/{pid} endpoint. Otherwise, it will proceed to 'CONFIRMED' status as usual.

Request Body schema:
account_pid
required
string

Account public id.

amount
required
integer >= 0

Transaction amount in cents.

currency
required
string
Value: "EUR"
required
object
required
object

Remittance information object.

Responses

Request samples

Content type
{
  • "account_pid": "KFGKJ5L27ASGTZAO",
  • "amount": 100,
  • "currency": "EUR",
  • "recipient": {
    },
  • "remittance_information": {
    }
}

Response samples

Content type
application/json
{
  • "pid": "UXNZ6IWJ2JESLXP3",
  • "account_pid": "KFGKJ5L27ASGTZAO",
  • "amount": 1485,
  • "fee": 15,
  • "currency": "EUR",
  • "added": "1698062541.845098",
  • "sender": {
    },
  • "recipient": {
    },
  • "remittance_information": {
    },
  • "source": "WEB",
  • "kind": "CREDIT",
  • "status": "DONE",
  • "vop": {
    },
  • "orgnl_tx": {
    }
}

Retrieve Transaction Details

Returns transaction details.

path Parameters
pid
required
string

Responses

Response samples

Content type
application/json
{
  • "pid": "UXNZ6IWJ2JESLXP3",
  • "account_pid": "KFGKJ5L27ASGTZAO",
  • "amount": 1485,
  • "fee": 15,
  • "currency": "EUR",
  • "added": "1698062541.845098",
  • "sender": {
    },
  • "recipient": {
    },
  • "remittance_information": {
    },
  • "source": "WEB",
  • "kind": "CREDIT",
  • "status": "DONE",
  • "vop": {
    },
  • "orgnl_tx": {
    }
}

List Account Transactions

Returns paginated list of transactions for specific account with account_pid.

query Parameters
cursor
string

The pagination cursor value.

account_pid
required
string

Account public id.

kind
string
Enum: "CREDIT" "DEBIT" "FEE"

kind

added__lte
string

Transaction added timestamp filter (in milliseconds).

added__gte
string

Transaction added timestamp filter (in milliseconds).

Responses

Response samples

Content type
application/json
{
  • "next": "string",
  • "previous": "string",
  • "results": [
    ]
}

Update Transaction

Update properties of a transaction. This endpoint can be used to programmatically accept or reject a transaction pending VOP confirmation. This action is only possible if the transaction is in 'CREATED' status and has a VOP match_type other than 'MTCH'.

path Parameters
pid
required
string

The public ID of the transaction to update.

Request Body schema: application/json
accept_vop
boolean

Set to 'true' to accept the VOP result and proceed with the transaction, or 'false' to cancel it.

Responses

Request samples

Content type
application/json
{
  • "accept_vop": true
}

Response samples

Content type
application/json
{
  • "pid": "UXNZ6IWJ2JESLXP3",
  • "account_pid": "KFGKJ5L27ASGTZAO",
  • "amount": 1485,
  • "fee": 15,
  • "currency": "EUR",
  • "added": "1698062541.845098",
  • "sender": {
    },
  • "recipient": {
    },
  • "remittance_information": {
    },
  • "source": "WEB",
  • "kind": "CREDIT",
  • "status": "DONE",
  • "vop": {
    },
  • "orgnl_tx": {
    }
}

Webhooks

transaction.created Webhook

Request Body schema: application/json

Occurs when transaction is created in the system.

pid
required
string
account_pid
required
string

Account public id.

amount
required
integer >= 0

Transaction amount in cents.

fee
required
integer
currency
required
string
Value: "EUR"
added
required
string <date-time>
object or null

May be null for returned or fee transactions.

object or null

May be null for fee transactions.

required
object

Remittance information object.

source
required
string
Enum: "WEB" "APP" "ACCOUNT_API" "BAAS_API" "CARD"
kind
required
string
Enum: "CREDIT" "DEBIT" "FEE"
status
required
string
Enum: "PENDING" "DONE" "REJECTED" "CANCELLED"
object or null

Verification of Payee (VOP) check result. Null if VOP is not applicable.

object or null

Information about original transaction in case this is a returned/rejected transaction. Null if not applicable.

Responses

Request samples

Content type
application/json
{
  • "pid": "UXNZ6IWJ2JESLXP3",
  • "account_pid": "KFGKJ5L27ASGTZAO",
  • "amount": 1485,
  • "fee": 15,
  • "currency": "EUR",
  • "added": "1698062541.845098",
  • "sender": {
    },
  • "recipient": {
    },
  • "remittance_information": {
    },
  • "source": "WEB",
  • "kind": "CREDIT",
  • "status": "DONE",
  • "vop": {
    },
  • "orgnl_tx": {
    }
}

transaction.updated Webhook

Request Body schema: application/json

Occurs when a transaction status updated.

pid
required
string
account_pid
required
string

Account public id.

amount
required
integer >= 0

Transaction amount in cents.

fee
required
integer
currency
required
string
Value: "EUR"
added
required
string <date-time>
object or null

May be null for returned or fee transactions.

object or null

May be null for fee transactions.

required
object

Remittance information object.

source
required
string
Enum: "WEB" "APP" "ACCOUNT_API" "BAAS_API" "CARD"
kind
required
string
Enum: "CREDIT" "DEBIT" "FEE"
status
required
string
Enum: "PENDING" "DONE" "REJECTED" "CANCELLED"
object or null

Verification of Payee (VOP) check result. Null if VOP is not applicable.

object or null

Information about original transaction in case this is a returned/rejected transaction. Null if not applicable.

Responses

Request samples

Content type
application/json
{
  • "pid": "UXNZ6IWJ2JESLXP3",
  • "account_pid": "KFGKJ5L27ASGTZAO",
  • "amount": 1485,
  • "fee": 15,
  • "currency": "EUR",
  • "added": "1698062541.845098",
  • "sender": {
    },
  • "recipient": {
    },
  • "remittance_information": {
    },
  • "source": "WEB",
  • "kind": "CREDIT",
  • "status": "DONE",
  • "vop": {
    },
  • "orgnl_tx": {
    }
}

vop.created Webhook

Request Body schema: application/json

Occurs when a transaction is created and requires Verification of Payee (VOP) confirmation.

pid
required
string
account_pid
required
string

Account public id.

amount
required
integer >= 0

Transaction amount in cents.

fee
required
integer
currency
required
string
Value: "EUR"
added
required
string <date-time>
object or null

May be null for returned or fee transactions.

object or null

May be null for fee transactions.

required
object

Remittance information object.

source
required
string
Enum: "WEB" "APP" "ACCOUNT_API" "BAAS_API" "CARD"
kind
required
string
Enum: "CREDIT" "DEBIT" "FEE"
status
required
string
Enum: "PENDING" "DONE" "REJECTED" "CANCELLED"
object or null

Verification of Payee (VOP) check result. Null if VOP is not applicable.

object or null

Information about original transaction in case this is a returned/rejected transaction. Null if not applicable.

Responses

Request samples

Content type
application/json
{
  • "pid": "UXNZ6IWJ2JESLXP3",
  • "account_pid": "KFGKJ5L27ASGTZAO",
  • "amount": 1485,
  • "fee": 15,
  • "currency": "EUR",
  • "added": "1698062541.845098",
  • "sender": {
    },
  • "recipient": {
    },
  • "remittance_information": {
    },
  • "source": "WEB",
  • "kind": "CREDIT",
  • "status": "DONE",
  • "vop": {
    },
  • "orgnl_tx": {
    }
}

Response samples

Content type
application/json
{
  • "accept_vop": true,
  • "nonce": "string",
  • "signature": "string"
}

Narvi Payments Oy Ab is an Authorized Electronic Money Institution (EMI). Narvi’s EMI license is granted by the Finnish Financial Supervisory Authority (FIN FSA) with the registration number 3190214-6. Narvi’s license is Passportised to all European Union countries.
© 2026 Narvi. All Rights Reserved.v1.298.0