General information

Authentication

Secure communication between your system and the Nexpay API

To ensure secure communication between your system and the Nexpay API, every request must be signed using an authentication signature. This signature proves that the request was created by an authorized client and that its contents were not altered during transmission. Without a valid signature, the API will reject the request.

The signature is generated using your API key, secret key, request body, and a unique nonce value. Together, these elements ensure both integrity (the request is unchanged) and freshness (the request has not been replayed).

Request signature

apikey
string as generated by Nexpay required
API key generated in client portal (HTTP header field: X-API-KEY)
nonce
integer required
Unique monotonous number (HTTP header field: X-NONCE). Use a millisecond or microsecond timestamp.
signature
string representation of hmac-sha512 result required
Hmac-sha512 signature (HTTP header field: X-Signature) of the api-key, nonce, full request path and body, signed using the signature key generated in the client cabinet in the settings page.
For POST requests the body is a concatenation of parameters encoded in the x-www-form-urlencoded format.
fullPath = path [+ '?' + query]
// (example 1: /api/1/eurowallet/payments/status?externalPaymentId=0347563b-7c0f-486c-9e61-de38aa67b571)
// (example 2: /api/1/eurowallet/payments/history?account=LT933080020000000686&fromDate=2026-01-01)

message = apikey + '&' + nonce + fullPath [+ ? + requestBody]
// (example 1: 4c0af59aaad960538015f35eff051336&1499263537306/api/1/eurowallet/payments/status?externalPaymentId=0347563b-7c0f-486c-9e61-de38aa67b571)
// (example 2: 4c0af59aaad960538015f35eff051336&1499262973793/api/1/eurowallet/payments/history?account=LT933080020000000686&fromDate=2026-01-01)

signature = lower_case(hex(hmac_sha512(message.getBytes(‘UTF-8’), secret_key.getBytes(‘UTF-8’) )))

Nonce

The nonce is a client-generated, ever-increasing number included in each request. It prevents replay attacks and ensures that each request processed by the API is unique and newer than the last one.

Because the nonce must always increase, one of the most common integration errors is: Nonce is not monotonous.

This error means that the latest nonce your client sent was lower than (or equal to) a nonce that the API already received from you. In other words, the sequence of nonces was not strictly increasing.

Why this happens

You must ensure that every request uses a nonce higher than the previous one:

  • Request 1 → nonce = 1001
  • Request 2 → nonce = 1002
  • Request 3 → nonce = 1003

The error occurs if:

  • Request 2 reaches the server with a lower nonce (e.g., 1000).
  • Two requests accidentally use the same nonce (e.g., both 1001).
  • Network latency causes the server to process requests out of order.
    • For example, your “second” request (nonce 1002) might be processed before the “first” (nonce 1001).
    • When the earlier (lower) nonce arrives later, the API rejects it because it is no longer higher than the last stored value.

What to do

To avoid or fix nonce issues:

  • Ensure each new request uses a nonce value higher than the previous one you generated.
  • If you encounter the error, simply retry the request with a higher nonce.
  • Consider increasing the precision of your timestamp-based nonce (e.g., from milliseconds to microseconds) if you generate multiple requests in very short time intervals. Higher precision reduces the risk of generating duplicate or non-increasing nonce values.

Transaction signature

When creating an outgoing payment via POST /api/2/eurowallet/payments, you must include an additional mandatory parameter called transactionSignature.

This signature applies an extra level of security when initiating new payment orders, confirming that the request was created by an authorized client using the transaction signing secret assigned to your account.

How the transaction signature is generated

transactionSignature is calculated as a lower-case HMAC-SHA512 hex digest of a message string.

The message string is constructed by:

  1. Taking a predefined ordered list of request parameters.
  2. Concatenating them in that exact order.
  3. Joining them with "&" in the format:
     parameter1=value1&parameter2=value2&parameter3=value3...
    
  4. Computing:
     hex( hmac_sha512( message, transaction_signing_secret ) ).lower()
    

Common issues when generating signature

There are several frequent integration mistakes that can cause signature validation failures:

  1. Incorrect parameter order
    Parameters must be concatenated exactly in the order specified by Nexpay, not alphabetically or based on your internal object structure.
    requestTime=1001&account=ACC1&amount=10.00&beneficiaryName=John Smith
    

    Even if all values are the same, the signature will differ if the order is wrong.
  2. Including unused optional parameters
    If an optional parameter is not used (left empty), do not include it in the message string.
    Leaving “gaps” or including empty parameters changes the message and invalidates the signature.
    requestTime=1001&account=ACC1&amount=10.00&beneficiaryName=John Smith
    
  3. Using the wrong signing secret
    Signing must always be done using the outgoing transaction message signing secret.
    Using any other secret key (e.g., authentication signature secret, webhook secret, or client portal key) will result in invalid signatures.
  4. Escaping or encoding characters inside the signed message
    Do not escape or URL-encode characters when building the message to sign.
    • Do not replace spaces with %20
    • Do not escape #, /, +, : or any other characters
    • Do not apply URL encoding before signing

    The signature must be generated from the raw, plain-text concatenated string exactly as described.
    beneficiaryReference=Invoice #314950-392
    
  5. Not applying the request signature
    The transaction signature applies an additional layer of security along with the "request signature" sent for all requests. Make sure to first generate the transaction signature, add it to the request payload, and then apply the request signature on top.

Example signatures

  1. SEPA/SEPA Instant
    message = "requestTime=" + requestTime
            + "&account=" + account
            + "&amount=" + amount
            + "&beneficiaryName=" + beneficiaryName
            + "&beneficiaryAddress=" + beneficiaryAddress
            + "&beneficiaryAccount=" + beneficiaryAccount
            + "&beneficiaryReference=" + beneficiaryReference
            + "&externalPaymentId=" + externalPaymentId
    
    transactionSignature = lower_case(
        hex( hmac_sha512( message.getBytes("UTF-8"), secret_key ) )
    )
    

  2. SWIFT
    message = "requestTime=" + requestTime
            + "&account=" + account
            + "&amount=" + amount
            + "&networkType=" + networkType
            + "&beneficiaryName=" + beneficiaryName
            + "&beneficiaryAccount=" + beneficiaryAccount
            + "&beneficiaryReference=" + beneficiaryReference
            + "&beneficiaryBankBic=" + beneficiaryBankBic
            + "&beneficiaryBankName=" + beneficiaryBankName
            + "&externalPaymentId=" + externalPaymentId
            + "&beneficiaryAddressStreet=" + beneficiaryAddressStreet
            + "&beneficiaryAddressTown=" + beneficiaryAddressTown
            + "&beneficiaryAddressCountry=" + beneficiaryAddressCountry
    
    transactionSignature = lower_case(
        hex( hmac_sha512( message.getBytes("UTF-8"), secret_key ) )
    )