Background

Our Business API uses Access Tokens generated with the Authorization Code Flow from your backend to authorize your requests. These tokens must be kept secret and should never be exposed in client-side code. To achieve this, the Embed API and SDK provide a secure mechanism to proxy requests through your server.
In addition to the access token, the staging token is another piece of sensitive information that must be kept secret. When using the staging environment, include the staging token in the request headers when calling the Qonto API.

System Overview

The Qonto API provides a proxy endpoint that dispatches requests to other Qonto API endpoints. It expects a base64-encoded string that describes the call to be made to the target endpoint. Upon receiving this request, the proxy endpoint decodes the string and makes the request to the Qonto API on your behalf. The response is then returned to the caller, also base64-encoded. When using the Qonto SDK, you don’t need to handle the encoding/decoding of calls, the SDK manages this automatically. The overall flow involves creating an intermediary endpoint on your server that forwards requests prepared by the SDK to the Qonto API while including the access token in the request headers. This way, client-side code never has access to the access token, keeping it secure on your server. Here are the steps involved in the process shown in the diagram above:
1

Define the proxyRequestFunction

Initialize the SDK with a proxyRequestFunction parameter that calls your intermediary endpoint. Since only you know your endpoint details and how to call it, providing your implementation is how the SDK knows how to reach your intermediary endpoint.
2

Use the SDK normally

Once the SDK is initialized, you can use it as you normally would. Call any SDK function and await the response from your application.
3

The SDK uses the proxyRequestFunction to call your intermediary endpoint

When the SDK prepares the call to the API endpoint related to the function you called, it encodes the request and calls the proxyRequestFunction you provided during initialization.
4

Add the access token to the request in your intermediary endpoint

The intermediary endpoint receives the encoded request. It must make a request to the Qonto proxy endpoint including the access token as the Authorization header and the payload it receives as the data parameter in the body.
5

Get the response from Qonto API and return it to the SDK

Once your intermediary endpoint receives the response from the Qonto API, it returns it to the SDK without modification and in plain text format.
6

The SDK returns the response to your app

Once the SDK gets the response from your intermediary endpoint, it decodes the response and returns it to your application.

Example Implementation

Let’s implement a call to update a SEPA beneficiary using the proxy endpoint.

Step 1: Create the intermediary endpoint in your backend

We’ll assume an application written in TypeScript with Next.js. The intermediary endpoint will be created in the /app/api/embed-intermediary.ts file as a Next Route Handler:
import { NextRequest } from 'next/server';

const PROXY_ENDPOINT_URL =
  'https://thirdparty.qonto.com/v1/encoded_requests/dispatch';

/**
 * In a real-world scenario, these would not be hardcoded values,
 * and you would store them securely in your backend.
 */
const accessToken = 'your-access-token-here';
const stagingToken = 'your-staging-token-here';

export async function POST(req: NextRequest) {
  const payload = await req.text();
  const options = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
      /*
       * This is the main purpose of this intermediary endpoint: adding the access token
       * to the request we are making to the Qonto Embed API.
       */
      Authorization: `Bearer ${accessToken}`,
      /**
       * If you are using the staging environment to test your integration, you will also
       * need to provide the staging token obtained from your developer portal account.
       */
      'X-Qonto-Staging-Token': stagingToken,
    },
    /**
     * The Qonto Proxy endpoint expects a JSON body with a `data` field whose value
     * is the base64-encoded string we received
     */
    body: JSON.stringify({ data: payload }),
  };
  try {
    const response = await fetch(PROXY_ENDPOINT_URL, options);
    if (!response.ok) {
      throw new Error(response.statusText);
    }
    const { data } = await response.json();
    /**
     * We return the response from the Qonto Proxy endpoint to our caller without modification.
     */
    return new Response(data, {
      status: 200,
      headers: { 'Content-Type': 'text/plain' },
    });
  } catch {
    return Response.json(
      { error: 'Failed to call the Qonto Proxy endpoint' },
      { status: 500 },
    );
  }
}
The intermediary endpoint needs to be implemented only once and will be used for all SDK functions your application calls.

Step 2: Configure the SDK to call the intermediary endpoint from client-side code

On the client side, configure the SDK to call the intermediary endpoint you just created. Do this by passing the proxyRequestFunction option to the SDK initialize function:
import { initialize } from '@qonto/embed-sdk/common';

initialize({
  operationSettings: {
    proxyRequestFunction: async (payload: string) => {
      // Call our newly created intermediary endpoint
      const response = await fetch('/api/embed-intermediary', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        // Include the payload in the body without any modification
        body: payload,
      });
      // The response comes as plain text from our intermediary endpoint implementation,
      // so we return the response text directly. The SDK will receive it and be able
      // to decode it and use it as needed.
      return await response.text();
    },
  },
});
The proxyRequestFunction needs to be implemented only once and will be used for all SDK functions your application calls.

Step 3: Call the SDK to update the SEPA beneficiary

Now you can call the SDK to update the SEPA beneficiary. The SDK will prepare the request, encode it, and send it to your intermediary endpoint. The intermediary endpoint will then add the access token (and staging token) to the request headers, call the Qonto API, and return the response to the SDK, which will decode it and return it to you.
import { beneficiaries } from '@qonto/embed-sdk/beneficiaries';

const response = await beneficiaries.updateSepaBeneficiary({
  beneficiaryId: 'beneficiary-id',
  data: {
    name: 'New Name',
    email: 'the-new-email@example.com',
  },
});

console.log('Beneficiary updated:', response);

Conclusion

By following these steps, you have successfully implemented a proxy endpoint that allows you to securely interact with the Qonto API without exposing your access token to client-side code. This approach ensures that sensitive information remains protected while still enabling the functionality you need in your application.