### Akahu Apply API Key Generation Source: https://developers.akahu.nz/docs/akahu-apply-getting-started Instructions and visual guides on how to generate an API key for the Akahu Apply service through the web portal. ```APIDOC ## Akahu Apply API Key Generation ### Description This section details the process of generating an API key for the Akahu Apply service. Users with the 'admin' role can generate and manage API keys via the Akahu Apply web portal. ### Steps 1. Log in to Akahu Apply ([https://apply.akahu.nz/](https://apply.akahu.nz/)). 2. Navigate to Settings > Manage API keys. 3. Click "Create" and provide a name and optional expiry for the API key. 4. Click save to generate the API key. Ensure you copy the key securely as it will not be accessible again. ### Security Warning API keys grant access to sensitive organizational and customer data. Store API keys securely to prevent unauthorized access. ``` -------------------------------- ### GET /v1/me Source: https://developers.akahu.nz/docs/personal-apps Retrieve your user details by making a GET request to the 'me' endpoint. This is a basic example to confirm successful API access and authentication. ```APIDOC ## GET /v1/me ### Description Retrieve your user details by making a GET request to the 'me' endpoint. This is a basic example to confirm successful API access and authentication. ### Method GET ### Endpoint https://api.akahu.io/v1/me ### Parameters #### Query Parameters None #### Request Body None ### Request Example ``` GET https://api.akahu.io/v1/me Authorization: Bearer {{apiKey}} X-Akahu-Id: {{appToken}} ``` ### Response #### Success Response (200) Returns a JSON object containing user details. - **id** (string) - The unique identifier for the user. - **name** (string) - The name of the user. - **email** (string) - The email address of the user. #### Response Example ```json { "id": "usr_abc123", "name": "John Doe", "email": "john.doe@example.com" } ``` ``` -------------------------------- ### Verify Webhook Signature using C# Source: https://developers.akahu.nz/docs/reference-webhooks This C# example provides a method to verify Akahu webhook signatures. It formats the public key by removing newline characters and delimiters, then uses `System.Security.Cryptography.RSA` to import the public key and `VerifyData` to check the signature against the request body using SHA256 and PKCS1 padding. Ensure the correct public key, body, and signature are provided. ```csharp using System; using System.Security.Cryptography; using System.Text; namespace akahu { class Program { public static void Main(string[] args) { // GET /keys/{keyId} var publicKey = "-----BEGIN RSA PUBLIC KEY-----\n ..."; // request body as a string (before any parsing) var body = "{\"webhook_type\":\"PAYMENT\", ..."; // "x-akahu-signature" header var signature = "KdcB0al..."; var formattedPublicKey = publicKey .Replace("\\n", "") .Replace("-----BEGIN RSA PUBLIC KEY-----", "") .Replace("-----END RSA PUBLIC KEY-----", ""); int bytesRead = 0; var rsa = RSA.Create(); var pubKeyBytes = Convert.FromBase64String(formattedPublicKey); rsa.ImportRSAPublicKey(pubKeyBytes, out bytesRead); var result = rsa.VerifyData(Encoding.UTF8.GetBytes(body), Convert.FromBase64String(signature), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); if (result) { Console.WriteLine("This webhook is from Akahu!"); } else { Console.WriteLine("Invalid webhook caller!"); } } } } ``` -------------------------------- ### GET /keys/{keyID} Source: https://developers.akahu.nz/docs/reference-webhooks Retrieve the public signing key used by Akahu to sign webhook requests. ```APIDOC ## GET /keys/{keyID} ### Description Retrieves the public RSA key used by Akahu to sign webhook payloads. This is necessary for verifying the authenticity of incoming webhooks. ### Method GET ### Endpoint /keys/{keyID} ### Parameters #### Path Parameters - **keyID** (string) - Required - The ID of the signing key, obtained from the `X-Akahu-Signing-Key` header of an incoming webhook. ### Response #### Success Response (200) - **success** (boolean) - Indicates if the key retrieval was successful. - **item** (string) - The public signing key in PEM format. #### Response Example ```json { "success": true, "item": "-----BEGIN RSA PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA...\n-----END RSA PUBLIC KEY-----" } ``` ``` -------------------------------- ### Webhook Event Handling Source: https://developers.akahu.nz/docs/reference-webhooks Guidelines for handling webhook events, emphasizing the importance of processing them correctly and potential issues with event ordering. ```APIDOC ## Webhook Event Handling ### Event Order Akahu cannot guarantee the delivery of events in the exact order they are generated. For instance, a 'payment: status = READY' webhook might be retried and delivered after a 'payment: status = SENT' webhook due to network issues or other delays. ### Recommended Practice To ensure your application's business logic functions correctly, it is recommended to fetch the complete object data from the Akahu API using the `item_id` provided in the webhook. This allows you to retrieve the most up-to-date information, regardless of the order in which events are processed. ``` -------------------------------- ### Example Public Signing Key Response (JSON) Source: https://developers.akahu.nz/docs/reference-webhooks Illustrates the expected JSON response structure when retrieving a public signing key from the Akahu API. The `item` field contains the public key in PEM format, which is essential for verifying webhook signatures. ```json { "success": true, "item": "-----BEGIN RSA PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA...\n-----END RSA PUBLIC KEY-----" } ``` -------------------------------- ### Transaction Webhooks Source: https://developers.akahu.nz/docs/reference-webhooks Webhooks related to transaction events, including initial updates, default updates, deletions, and cancellations. ```APIDOC ## Transaction Webhooks This section details the different transaction-related webhooks provided by Akahu. ### INITIAL_UPDATE **Description**: Akahu has retrieved historic transactions for an account after initial connection. This webhook will only be sent for accounts newly connected to Akahu. If the user has previously connected accounts to Akahu for use by another app, your app will only ever receive `DEFAULT_UPDATE` webhooks for those accounts. **Additional Fields**: - `item_id` (string) - The account ID. - `new_transactions` (integer) - The number of new transactions. - `new_transaction_ids` (array of strings) - An array of transaction IDs for the new transactions. ### DEFAULT_UPDATE **Description**: Akahu has retrieved new transactions or updated existing transactions. **Additional Fields**: - `item_id` (string) - The account ID. - `new_transactions` (integer) - The number of new or updated transactions. - `new_transaction_ids` (array of strings) - An array of transaction IDs for the new or updated transactions. ### DELETE **Description**: One or more transactions have been deleted. **Additional Fields**: - `item_id` (string) - The account ID. - `removed_transactions` (array of strings) - An array of transaction IDs. ### WEBHOOK_CANCELLED **Description**: This webhook has been cancelled, for example if the user revokes your app. **Additional Fields**: - None ``` -------------------------------- ### POST /webhooks Source: https://developers.akahu.nz/docs/reference-webhooks Subscribe to webhooks for a specific user. This should generally be done after a successful OAuth token exchange. ```APIDOC ## POST /webhooks ### Description Subscribes your application to receive specific webhook events for a given user. ### Method POST ### Endpoint /webhooks ### Parameters #### Query Parameters - **userID** (string) - Required - The ID of the user for whom to subscribe to webhooks. #### Request Body - **event_type** (string) - Required - The type of event to subscribe to (e.g., 'transaction.created', 'account.updated'). - **callback_url** (string) - Required - The URL that Akahu will send webhook POST requests to. ### Request Example ```json { "event_type": "transaction.created", "callback_url": "https://your-app.com/webhook-handler" } ``` ### Response #### Success Response (200) - **success** (boolean) - Indicates if the subscription was successful. - **item** (object) - Details of the created webhook subscription. - **id** (string) - The unique identifier for the webhook subscription. - **user_id** (string) - The ID of the user associated with the subscription. - **event_type** (string) - The type of event subscribed to. - **callback_url** (string) - The URL where webhooks are sent. - **created_at** (string) - The timestamp when the subscription was created. #### Response Example ```json { "success": true, "item": { "id": "wh_123abc", "user_id": "usr_abc123", "event_type": "transaction.created", "callback_url": "https://your-app.com/webhook-handler", "created_at": "2023-10-27T10:00:00Z" } } ``` ``` -------------------------------- ### Webhook Retry and Disable Logic Source: https://developers.akahu.nz/docs/reference-webhooks Understand Akahu's policies regarding webhook delivery retries and potential disabling of webhooks due to repeated delivery failures. ```APIDOC ## Webhook Retry and Disable Logic ### Retry Logic Akahu will attempt to deliver your webhook event for up to three days, with attempts sent approximately every hour. If initial delivery fails and you delete your webhook before a retry attempt, no further retries will occur. ### Disable Logic Akahu may disable webhooks if your endpoint consistently fails to return a 200 HTTP status code for multiple events over several days. ``` -------------------------------- ### Verify Webhook Signature using Python Source: https://developers.akahu.nz/docs/reference-webhooks This Python example demonstrates webhook signature verification using the 'cryptography' library. It defines a `verify_signature` function that takes the PEM-formatted public key, the base64 encoded signature, and the raw request body (as bytes). The function deserializes the public key, applies padding, and verifies the signature against the hashed request body. Ensure the correct key, signature, and body are passed. ```python import json import base64 from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.exceptions import InvalidSignature def verify_signature(public_key: str, signature: str, request_body: bytes) -> None: """Verify that the request body has been signed by Akahu. Arguments: public_key -- The PEM formatted public key retrieved from the Akahu API signature -- The base64 encoded value from the "X-Akahu-Signature" header ``` -------------------------------- ### Transfer Webhooks Source: https://developers.akahu.nz/docs/reference-webhooks Webhooks related to transfer events, including status updates, received funds, and cancellations. ```APIDOC ## Transfer Webhooks This section details the different transfer-related webhooks provided by Akahu. ### UPDATE **Description**: A transfer has changed its status. **Additional Fields**: - `item_id` (string) - The transfer ID. - `status` (string) - The new status. - `status_text` (string, optional) - A description of the status, if present. ### RECEIVED **Description**: The funds have arrived at the destination account. **Additional Fields**: - `item_id` (string) - The transfer ID. - `received_at` (string) - The time that Akahu identified the funds as received. ### WEBHOOK_CANCELLED **Description**: This webhook has been cancelled, for example if the user revokes your app. **Additional Fields**: - None ``` -------------------------------- ### Webhook Structure Source: https://developers.akahu.nz/docs/reference-webhooks Details on the hierarchical structure of Akahu webhooks, including `webhook_type`, `webhook_code`, and common fields. ```APIDOC ## Webhook Structure Akahu webhooks follow a hierarchical structure. The top level is `webhook_type`, indicating the type of object that triggered the event (e.g., `USER`, `ACCOUNT`, `TRANSACTION`). Within each `webhook_type`, `webhook_code` specifies the event type (e.g., `UPDATE`, `DELETE`). ### Basic Structure All webhooks include the following fields: ```json { "webhook_type": "", "webhook_code": "", "state": "" // Optional: If supplied when creating the webhook } ``` ### Supported Webhook Types #### TOKEN | Code | Description | Additional Fields | | -------- | ---------------------------------------- | ----------------- | | `DELETE` | This User Access Token has been revoked. | `item_id` The User Access Token. | ``` -------------------------------- ### Test Request to Verify API Key Source: https://developers.akahu.nz/docs/akahu-apply-getting-started A cURL command to test your generated API key by making a request to the organization endpoint. ```APIDOC ## Making a Request ### Description This endpoint allows you to verify your API key by making a test request to retrieve basic information about your organization. ### Method GET ### Endpoint `/v1/orgs/current` ### Parameters #### Headers - **Authorisation** (string) - Required - `Bearer {API_KEY}` ### Request Example ```shell curl https://api.apply.akahu.nz/v1/orgs/current \ --header 'Authorisation: Bearer {API_KEY}' ``` ### Response #### Success Response (200) - **_id** (string) - The unique identifier for the organization. - **name** (string) - The name of the organization. - **logo** (string) - A URL to the organization's logo. #### Response Example ```json { "_id": "org_s5l7kht0o1oknb0fl15i31rq", "name": "ACME Finance", "logo": "https://public-assets.apply.akahu.nz/org_s5l7kht0o1oknb0fl15i31rq/logo" } ``` ``` -------------------------------- ### Akahu API Search Endpoint Request Example (cURL) Source: https://developers.akahu.nz/docs/genie An example of how to send a POST request to the Akahu Genie search endpoint using cURL. This snippet demonstrates the required headers and the JSON payload format for transaction enrichment queries. Ensure your API key is correctly substituted. ```shell curl --request POST 'https://api.genie.akahu.io/v1/search' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '[\ { "_id": "1", "description": "CJ PALMERSTON NTH - 203PALM NTH", "_connection": "conn_cjgaaqcna000001ldwof8tvj0", "amount": -4.9 }, { "_id": "2", "description": "CARD 2293 WHOLEMEAL TRAD CO LTDTAKAKA", "_connection": "conn_cjgaaqcna000001ldwof8tvj0", "amount": -25.1 } ]' ``` -------------------------------- ### Connection Examples (Migration Mode) Source: https://developers.akahu.nz/docs/official-open-banking-migration This JSON array shows two connection entries for a bank in migration mode: a classic connection with `new_connections_enabled: false` and an official connection. ```json [ { "_id": "conn_cjgaaozdo000001mrnqmkl1m0", "name": "Westpac", "logo": "https://cdn.akahu.nz/logos/...", "connection_type": "classic", "new_connections_enabled": false }, { "_id": "conn_cmb01ceg1000008l53yw4a6ez", "_classic": "conn_cjgaaozdo000001mrnqmkl1m0", "name": "Westpac", "logo": "https://cdn.akahu.nz/logos/...", "connection_type": "official", "new_connections_enabled": true, "mode": "migration" } ] ``` -------------------------------- ### Verify Webhook Signature with Akahu SDK (JavaScript) Source: https://developers.akahu.nz/docs/reference-webhooks Easily verify incoming webhook signatures using the Akahu JavaScript SDK's `validateWebhook` method. This simplifies the process by handling the signature and key verification internally. Ensure you have the SDK installed (`npm install akahu`). ```javascript import { AkahuClient } from 'akahu'; // Assuming you have the raw request body, signature, and key ID const signature = req.headers['x-akahu-signature']; const signingKeyId = req.headers['x-akahu-signing-key']; const requestBody = req.body; // Initialize AkahuClient with your API key const client = new AkahuClient('YOUR_API_KEY'); try { const isValid = await client.webhooks.validateWebhook( requestBody, signature, signingKeyId ); if (isValid) { console.log('Webhook signature is valid!'); // Process the webhook data } else { console.error('Webhook signature verification failed!'); // Handle invalid signature } } catch (error) { console.error('Error validating webhook:', error); // Handle other errors during validation } ``` -------------------------------- ### Create Application Source: https://developers.akahu.nz/docs/akahu-apply-workflows Creates a new Application for collecting data resources. The 'reference' field is mandatory for system identification. ```APIDOC ## POST /v1/applications ### Description Use this endpoint to create a new Application for data Resources to be collected into. The `reference` field must be included to identify the Application in Akahu Apply using a reference from your system. Create a new Application for each logical data boundary in your system. ### Method POST ### Endpoint /v1/applications ### Parameters #### Request Body - **reference** (string) - Required - A reference from your system to identify the Application. ### Request Example ```json { "reference": "unique-app-ref-123" } ``` ### Response #### Success Response (201 Created) - **id** (string) - The unique identifier for the created Application. - **reference** (string) - The reference provided during creation. - **created_at** (string) - Timestamp of when the application was created. #### Response Example ```json { "id": "app_abc123", "reference": "unique-app-ref-123", "created_at": "2023-10-27T10:00:00Z" } ``` ``` -------------------------------- ### Verify Webhook Signature using Node.js Source: https://developers.akahu.nz/docs/reference-webhooks This Node.js example demonstrates how to verify an incoming webhook signature from Akahu. It uses the built-in 'crypto' module to compute the RSA-SHA256 signature of the request body and compares it with the 'X-Akahu-Signature' header. Ensure you have the correct public key and request body content for accurate verification. ```javascript const crypto = require("crypto"); // GET /keys/{keyId} const publicKey = "-----BEGIN RSA PUBLIC KEY-----\n ..."; // request body as a string (before any parsing) const body = "{\"webhook_type\":\"PAYMENT\", ..."; // "x-akahu-signature" header const signature = "KdcB0al ..."; const verify = crypto.createVerify("sha256"); verify.update(body); verify.end(); const isValid = verify.verify( publicKey, signature, "base64" ); if (isValid) { console.log("This webhook is from Akahu!"); } else { console.log("Invalid webhook caller!"); } ``` -------------------------------- ### Official Connection Example (Strict Mode) Source: https://developers.akahu.nz/docs/official-open-banking-migration This JSON object demonstrates the structure of an official connection when Akahu is in strict mode. It includes identifiers, names, logos, connection type, and mode. ```json { "_id": "conn_cm4hlog270000914n33hj6tqq", "name": "ASB", "logo": "https://cdn.akahu.nz/logos/...", "connection_type": "official", "new_connections_enabled": true, "mode": "strict" } ``` -------------------------------- ### Retrieve Public Signing Key from Akahu API (Shell) Source: https://developers.akahu.nz/docs/reference-webhooks Fetch the public RSA signing key required for webhook verification by making a GET request to the Akahu API. This method is useful when direct SDK integration is not feasible or when implementing verification in different languages. The response contains the public key in PEM format. ```shell # Replace {keyID} with the actual key ID from the X-Akahu-Signing-Key header KEY_ID="YOUR_KEY_ID" curl -X GET "https://api.akahu.io/v1/keys/$KEY_ID" \ -H "Authorization: Bearer YOUR_API_KEY" ``` -------------------------------- ### Verify Webhook Signature using Java Source: https://developers.akahu.nz/docs/reference-webhooks This Java example shows how to verify Akahu webhook signatures, requiring the Bouncy Castle library for cryptographic operations. It parses the provided RSA public key, computes the RSA-SHA256 signature of the request body, and validates it against the 'X-Akahu-Signature' header. The `getRSAPublicKeyFromString` and `validateSignature` methods handle key parsing and signature verification respectively. ```java // Code snippet contributed by Christian Mitchell (https://bankroll.co.nz) // requires BounceCastle https://www.bouncycastle.org/java.html package com.akahu; import java.math.BigInteger; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; import java.security.Signature; import java.util.Base64; public class Main { private static RSAPublicKey getRSAPublicKeyFromString(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException { String formattedPublicKey = publicKey .replaceAll("\\n", "") .replace("-----BEGIN RSA PUBLIC KEY-----", "") .replace("-----END RSA PUBLIC KEY-----", ""); org.bouncycastle.asn1.pkcs.RSAPublicKey rsaPublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(Base64.getDecoder().decode(formattedPublicKey)); BigInteger modulus = rsaPublicKey.getModulus(); BigInteger publicExponent = rsaPublicKey.getPublicExponent(); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent); return (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(keySpec); } private static boolean validateSignature(String requestSignature, String requestBody, String publicKey) throws Exception { RSAPublicKey masterPublicKey = getRSAPublicKeyFromString(publicKey); Signature signature = Signature.getInstance("SHA256withRSA"); signature.initVerify(masterPublicKey); signature.update(requestBody.getBytes()); return signature.verify(Base64.getDecoder().decode(requestSignature.getBytes())); } public static void main(String[] args) throws Exception { // GET /keys/{keyId} String publicKey = "-----BEGIN RSA PUBLIC KEY-----\n ..."; // request body as a string (before any parsing) String body = "{\"webhook_type\":\"PAYMENT\", ..."; // "x-akahu-signature" header String signature = "KdcB0al..."; boolean result = validateSignature(signature, body, publicKey); if (result) { System.out.println("This webhook is from Akahu!"); } else { System.out.println("Invalid webhook caller!"); } } } ``` -------------------------------- ### Construct Akahu Authorization URL Source: https://developers.akahu.nz/docs/authorizing-with-oauth2 This example demonstrates how to construct the authorization URL for the Akahu OAuth flow. It includes common parameters like response_type, client_id, redirect_uri, scope, and state. Ensure all URLs and parameters are properly encoded. ```javascript function constructAuthUrl(clientId, redirectUri, scope, state = '', email = '', connection = '') { const baseUrl = 'https://oauth.akahu.nz'; const params = { response_type: 'code', client_id: clientId, redirect_uri: encodeURIComponent(redirectUri), scope: scope, state: state }; if (email) { params.email = encodeURIComponent(email); } if (connection) { params.connection = connection; } const queryString = Object.keys(params) .map(key => `${key}=${params[key]}`) .join('&'); return `${baseUrl}?${queryString}`; } // Example Usage: const clientId = 'YOUR_APP_TOKEN'; const redirectUri = 'https://your-app.com/auth/akahu'; const scope = 'ENDURING_CONSENT'; const state = '1234567890'; const userEmail = 'user@example.com'; const authUrl = constructAuthUrl(clientId, redirectUri, scope, state, userEmail); console.log(authUrl); ``` ```python import urllib.parse def construct_auth_url(client_id, redirect_uri, scope, state='', email='', connection=''): base_url = 'https://oauth.akahu.nz' params = { 'response_type': 'code', 'client_id': client_id, 'redirect_uri': redirect_uri, 'scope': scope, 'state': state } if email: params['email'] = email if connection: params['connection'] = connection query_string = urllib.parse.urlencode(params) return f"{base_url}?{query_string}" # Example Usage: client_id = 'YOUR_APP_TOKEN' redirect_uri = 'https://your-app.com/auth/akahu' scope = 'ENDURING_CONSENT' state = '1234567890' user_email = 'user@example.com' auth_url = construct_auth_url(client_id, redirect_uri, scope, state=state, email=user_email) print(auth_url) ``` -------------------------------- ### Initiating the Authorization Request Source: https://developers.akahu.nz/docs/authorizing-with-oauth2 To start the OAuth flow, redirect the user to the Akahu authorization endpoint with the required query parameters. ```APIDOC ## GET /authorize ### Description Initiates the OAuth 2.0 authorization flow by redirecting the user to the Akahu authorization server. ### Method GET ### Endpoint `https://oauth.akahu.nz` ### Parameters #### Query Parameters - **response_type** (string) - Required - The type of OAuth response. Currently, only `code` is supported. - **client_id** (string) - Required - Your application's App ID Token. - **email** (string) - Optional - The user's email address. - **connection** (string) - Optional - Directs the user to a specific connection. - **redirect_uri** (string) - Required - The URI to redirect the user to after authorization. Must match one of your app's registered Redirect URIs. - **scope** (string) - Required - The scope of the OAuth flow. `ENDURING_CONSENT` is a common value. Can be a space-separated list for specific scopes. - **state** (string) - Optional (Required for accredited apps) - An arbitrary string to maintain state and prevent CSRF attacks. It will be returned with the Authorization Code. ### Request Example ```text https://oauth.akahu.nz?response_type=code&client_id={{appToken}}&email=user@example.com&connection=conn_1234&redirect_uri=https://example.com/auth/akahu&scope=ENDURING_CONSENT&state=1234567890 ``` ### Response #### Redirects to `redirect_uri` with query parameters. #### Success Response (User Accepts) - **code** (string) - An Authorization Code used in the next step. - **state** (string) - The `state` parameter value from the request. - **source** (string) - For OAuth requests, this is always `oauth`. - **event** (string) - The user's action: `ACCEPT`, `REVOKE`, or `UPDATE`. #### Error Response - **error** (string) - An OAuth 2.0 error code (e.g., `access_denied`, `invalid_request`). - **error_description** (string) - Optional. A more detailed description of the error. ``` -------------------------------- ### Webhook Verification API Source: https://developers.akahu.nz/docs/reference-webhooks This API endpoint is used to verify the authenticity of incoming webhooks by verifying their signatures. ```APIDOC ## POST /webhooks/verify ### Description Verifies the signature of an incoming webhook to ensure it originated from Akahu. ### Method POST ### Endpoint /webhooks/verify ### Parameters #### Query Parameters - **X-Akahu-Signature** (string) - Required - The base64 encoded RSA-SHA256 signature of the webhook body. #### Request Body - **body** (string) - Required - The raw, unparsed webhook request body. - **publicKey** (string) - Required - The PEM formatted public signing key obtained from GET /keys/{keyId}. ### Request Example ```json { "body": "{\"webhook_type\":\"PAYMENT\", ...}", "publicKey": "-----BEGIN RSA PUBLIC KEY-----\n ...\n-----END RSA PUBLIC KEY-----" } ``` ### Response #### Success Response (200) - **isValid** (boolean) - True if the signature is valid, false otherwise. #### Response Example ```json { "isValid": true } ``` #### Error Response (400) - **error** (string) - Description of the error (e.g., "Invalid signature", "Invalid key format"). ``` -------------------------------- ### Initializing Akahu JS SDK with Retries Source: https://developers.akahu.nz/docs/idempotent-requests Demonstrates initializing the Akahu JS SDK with a specified number of retries to handle network errors during requests. This is crucial for leveraging the SDK's support for idempotent requests. ```javascript const akahu = new AkahuClient({ appToken: process.env.AKAHU_APP_TOKEN, retries: 3 // <-- Retry requests 3 times on network errors }); ```