Skip to main content

Authentication

The finperks Giftcard API requires requests to be signed for authentication. finperks provides a client id and client secret as credentials. These credentials are scoped to the specific API environment and may be scoped further to only supporting specific actions to allow safe usage in accordance to the associated risk for the use case. The secret will never have to be included in plain text in a request, but is only used to create the signature.

The API uses this signature algorithm in addition to transport encryption via HTTPS. More information about HTTPS certificate verification can be found under Accessing the API.

Request Signature

Authorization header format for API requests

Authorization: FP1-HMAC-SHA256 KeyId=ID, Signature=SIGNATURE

For requests, the API expects a standard HTTP Authorization header with a custom authentication scheme, FP1-HMAC-SHA256.

Replace ID with your client id and SIGNATURE with a signature based on certain parts of the request. The specific calculation method to build the signature is described below.

Example Date header

Date: Wed, 09 Jul 2025 16:17:31 GMT

The signature includes the current time, which must be included in the request's Date header.

When the Authorization header is missing or invalid, the API returns HTTP status 401 with a WWW-Authenticate: FP1-HMAC-SHA256 header and an error.

Webhook Signature

For webhooks, we provide the signature in a custom header, Fp-Signature.

Fp-Signature header format for webhook requests

Fp-Signature: FP1-HMAC-SHA256 KeyId=ID, Signature=SIGNATURE

ID will be replaced by the key that was used for the Signature to optimize validation during key rotation.

SIGNATURE will be replaced with a signature based on certain parts of the request. The algorithm for calculating the signature is described below. Webhook requests contain a Date header as used in Request Signature.

When receiving webhooks, always verify the signature.

Calculating the Signature

Calculating the signature means generating a string with certain parameters and then using your client secret to sign the string with HMAC-SHA256. This section describes how the signature can be calculated. It also contains a signature generator which you can use to confirm the correctness of your implementation.

The string to sign contains the parameters in the following order, separated by newlines (line feed characters \n only).

Example String to sign

api.finperks.com:443
POST
/v1/orders

Wed, 09 Jul 2025 16:17:31 GMT
5433c546-82d1-4105-baf7-7243a562273d
9123e49bd48ab640096f65ed7b21fc2a1006a799dad0553a20ec9aff745be887
  • Host and port, separated by a colon, e.g. api.finperks.com:443. The host must match the host in the request's Host-header.
  • HTTP Method, e.g. POST
  • Path, e.g. /v1/orders
  • Query string without question mark
  • Date as specified in the Date header, e.g. Wed, 09 Jul 2025 16:17:31 GMT (make sure the date and your system's clock is correct, it must be within a small window around the current time)
  • Idempotency key as specified in the Idempotency-Key header (see below, may be empty if the header is not used for a request)
  • SHA-256 digest of the request body (SHA-256 of an empty string if the body is empty), e.g. aa4edf67aba250d4cb4fb483835d0e40bad5ef7f17de8f4efa8c2f3eb12688c2

The newlines are always necessary, regardless of whether a value is empty or not, so that number of lines in the string to sign is always the same. Do not add a newline after the body digest. Make sure to only use line feed characters, and no carriage returns. This is important, as we use the same mechanism to calculate the signature to verify your credentials.

The last step is signing the string with your client secret. Use the client secret in the form finperks provides it (do not convert the data to binary).

Example Key: 924f85f0-3581-4678-967a-5eb5615a0a41

Bash Example showing HMAC-SHA256 signing

signature=$(printf "%s" "$string_to_sign" | openssl dgst -sha256 -hmac "$api_key" | sed 's/^.* //')
echo "$signature"

Use the client secret to sign the string using HMAC with SHA-256 as hash function and encode the resulting bytes in hexidecimal form.

With the example string to sign and example key above, you can calculate the following signature:

Example Signature: 0ce8cbdab32f25d12fb0535740ab6993fdc3fd67cf4b5ac14c33588337b36066

Code Examples

Below are complete examples for generating signatures in various languages. Each example includes:

  • A helper function for formatting the Date header in RFC 7231 format
  • The signature generation function
  • A usage example verified against the test data
Common Pitfall: Date Header Formatting

A frequent cause of signature validation failures is an incorrectly formatted day in the Date header. The day must always be two digits with a leading zero (e.g., 09 not 9).

Many standard library date formatters produce Wed, 9 Jul 2025 instead of Wed, 09 Jul 2025, causing signature mismatches.

import hashlib
import hmac
from datetime import datetime, timezone


def get_http_date() -> str:
"""
Returns the current UTC time in RFC 7231 format.
Python's %d format specifier already includes the leading zero.
"""
now = datetime.now(timezone.utc)
return now.strftime('%a, %d %b %Y %H:%M:%S GMT')


def generate_signature(
client_secret: str,
host_with_port: str,
method: str,
path: str,
query_string: str,
date_header: str,
idempotency_key: str,
body: str
) -> str:
body_digest = hashlib.sha256(body.encode('utf-8')).hexdigest()

string_to_sign = '\n'.join([
host_with_port,
method,
path,
query_string,
date_header,
idempotency_key,
body_digest
])

return hmac.new(
client_secret.encode('utf-8'),
string_to_sign.encode('utf-8'),
hashlib.sha256
).hexdigest()


# Usage example with test data
if __name__ == '__main__':
signature = generate_signature(
client_secret='30ce906050147eab919e8258871c45e7e3a3cb07',
host_with_port='api.finperks.com:443',
method='POST',
path='/v1/orders',
query_string='',
date_header='Sun, 06 Nov 2005 08:49:37 GMT',
idempotency_key='123e4567-e89b-12d3-a456-426614174000',
body='{"amount":1000,"currency":"USD"}'
)

expected = '786bd09c754ad301bb267a158c7b79a5a5a262dc50656c6d24c2c49bb49a5270'
assert signature == expected, f'Signature mismatch: {signature}'
print(f'Signature: {signature}')

# For live requests, use get_http_date() instead of a fixed date:
# date_header = get_http_date()
Test Data for Verification

Use these test cases to verify your implementation produces the expected signatures.

POST Request:

ParameterValue
Secret30ce906050147eab919e8258871c45e7e3a3cb07
Hostapi.finperks.com:443
MethodPOST
Path/v1/orders
Query String(empty)
DateSun, 06 Nov 2005 08:49:37 GMT
Idempotency Key123e4567-e89b-12d3-a456-426614174000
Body{"amount":1000,"currency":"USD"}
Expected Signature786bd09c754ad301bb267a158c7b79a5a5a262dc50656c6d24c2c49bb49a5270

GET Request:

ParameterValue
Secret30ce906050147eab919e8258871c45e7e3a3cb07
Hostapi.finperks.com:443
MethodGET
Path/v1/products
Query String?countrycode=DE
DateSun, 06 Nov 2005 08:49:37 GMT
Idempotency Key(empty)
Body(empty)
Expected Signature3c8e65ab28539ace0817369d6943584d78be271dbe93bcb5408ee98a0141e30e

Example

Example Request Headers with signature in the Authorization header

POST /v1/orders HTTP/1.1
Authorization: FP1-HMAC-SHA256 KeyId=6b0dff1a-f729-42d1-9eed-d2f17ef5aedb, Signature=0ce8cbdab32f25d12fb0535740ab6993fdc3fd67cf4b5ac14c33588337b36066
Date: Wed, 09 Jul 2025 16:17:31 GMT
Host: api.finperks.com

Signature Generator

This signature generator allows you to verify and debug your implementation of the signature algorithm.

Note:

  • Make sure to not have extra whitespace in any of the fields.
  • Make sure you do not accidentally change the newline characters when copying code between the browser and your text editor. E.g. Windows often adds carriage return characters in addition to line feed characters.

The bytes put into the signature must be the same sent with the actual request, so different kinds of newlines and whitespace can invalidate the signature.