> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fastflowpe.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Generate a short-lived X-API-Key via the FastFlowPe auth API or merchant dashboard, then attach it as a header on every API request.

FastFlowPe separates your identity from your session. Your **Client ID** and **Client Secret** are permanent, you use them exclusively to obtain a session token. Your **X-API-Key** is that session token: short-lived, expiring after **30 minutes**, and required on every API request you make. Once a key expires or a new one is generated, the old key is immediately invalidated.

<Callout icon="pencil">
  **Quick Reference**

  **Required:** `client-id`, `client-secret`

  **Returns:** `x_api_key` (valid for 30 minutes)

  **Endpoint:** `GET https://auth.fastflowpe.com/system/generate_x_api_token_merchant`
</Callout>

You can acquire a new X-API-Key in two ways: via the authentication API, or directly from the merchant dashboard.

## Method 1: Generate via API

Use this method in production systems. Send a GET request to the FastFlowPe authentication endpoint with your `client-id` and `client-secret` as headers. The response returns a fresh X-API-Key you can use immediately.

**Request**

| Field                   | Value                                                              |
| ----------------------- | ------------------------------------------------------------------ |
| Method                  | `GET`                                                              |
| URL                     | `https://auth.fastflowpe.com/system/generate_x_api_token_merchant` |
| Header: `client-id`     | Your Client ID from the dashboard                                  |
| Header: `client-secret` | Your Client Secret from the dashboard                              |

<RequestExample>
  ```bash cURL theme={"dark"}
  curl --location 'https://auth.fastflowpe.com/system/generate_x_api_token_merchant' \
  --header 'Accept: application/json' \
  --header 'client-id: Your-Client-ID-Here' \
  --header 'client-secret: Your-Client-Secret-Here'
  ```

  ```python Python theme={"dark"}
  import requests

  url = "https://auth.fastflowpe.com/system/generate_x_api_token_merchant"
  headers = {
      "Accept": "application/json",
      "client-id": "Your-Client-ID-Here",
      "client-secret": "Your-Client-Secret-Here",
  }

  response = requests.post(url, headers=headers)
  x_api_key = response.json()["data"]["x_api_key"]
  print(x_api_key)
  ```

  ```javascript Node.js theme={"dark"}
  const url = "https://auth.fastflowpe.com/system/generate_x_api_token_merchant";

  const response = await fetch(url, {
    method: "POST",
    headers: {
      Accept: "application/json",
      "client-id": "Your-Client-ID-Here",
      "client-secret": "Your-Client-Secret-Here",
    },
  });

  const { data } = await response.json();
  console.log(data.x_api_key);
  ```

  ```php PHP theme={"dark"}
  <?php
  $ch = curl_init("https://auth.fastflowpe.com/system/generate_x_api_token_merchant");
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      "Accept: application/json",
      "client-id: Your-Client-ID-Here",
      "client-secret: Your-Client-Secret-Here",
  ]);

  $response = json_decode(curl_exec($ch), true);
  curl_close($ch);
  echo $response["data"]["x_api_key"];
  ```

  ```go Go theme={"dark"}
  package main

  import (
      "encoding/json"
      "fmt"
      "net/http"
  )

  func main() {
      req, _ := http.NewRequest("POST", "https://auth.fastflowpe.com/system/generate_x_api_token_merchant", nil)
      req.Header.Set("Accept", "application/json")
      req.Header.Set("client-id", "Your-Client-ID-Here")
      req.Header.Set("client-secret", "Your-Client-Secret-Here")

      resp, _ := http.DefaultClient.Do(req)
      defer resp.Body.Close()

      var body struct {
          Data struct {
              XApiKey string `json:"x_api_key"`
          } `json:"data"`
      }
      json.NewDecoder(resp.Body).Decode(&body)
      fmt.Println(body.Data.XApiKey)
  }
  ```

  ```java Java theme={"dark"}
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;

  public class GenerateApiKey {
      public static void main(String[] args) throws Exception {
          HttpClient client = HttpClient.newHttpClient();
          HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create("https://auth.fastflowpe.com/system/generate_x_api_token_merchant"))
              .header("Accept", "application/json")
              .header("client-id", "Your-Client-ID-Here")
              .header("client-secret", "Your-Client-Secret-Here")
              .POST(HttpRequest.BodyPublishers.noBody())
              .build();

          HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
          System.out.println(response.body());
      }
  }
  ```

  ```ruby Ruby theme={"dark"}
  require 'net/http'
  require 'json'
  require 'uri'

  uri = URI('https://auth.fastflowpe.com/system/generate_x_api_token_merchant')
  request = Net::HTTP::Post.new(uri)
  request['Accept'] = 'application/json'
  request['client-id'] = 'Your-Client-ID-Here'
  request['client-secret'] = 'Your-Client-Secret-Here'

  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
  puts JSON.parse(response.body)['data']['x_api_key']
  ```
</RequestExample>

**Success Response**

<ResponseExample>
  ```json 200 OK theme={"dark"}
  {
      "status": "success",
      "status_code": 200,
      "message": "Merchant X-API-Key generated and saved.",
      "detail": null,
      "data": {
          "x_api_key": "<Your New x-api-key will come here>"
      }
  }
  ```
</ResponseExample>

Extract the value at `data.x_api_key` and store it securely in your application. Include it as an `x-api-key` header on every subsequent API call.

<Tip>
  Set up a cron job to call this endpoint every **29 minutes** so your system always has a valid key in rotation. Since keys expire at 30 minutes, a 29-minute refresh cycle gives you a one-minute buffer and prevents `401 Unauthorized` errors caused by token expiry mid-request.
</Tip>

<Note>
  When you generate a new X-API-Key, the previous key is **automatically and immediately invalidated**. If multiple services share the same merchant account, coordinate key rotation so one service does not invalidate another's active key.
</Note>

## Method 2: Generate via Dashboard

Use this method during development, testing, or whenever you need a one-off key without writing code. Log in to the merchant dashboard, navigate to the API settings page, and click the Generate Key button to issue a new X-API-Key instantly.

<Steps>
  <Step title="Log In to the Merchant Dashboard">
    Go to [https://go.fastflowpe.com/](https://go.fastflowpe.com/) and sign in with your registered email address and password.
  </Step>

  <Step title="Navigate to API Settings">
    From the main navigation, go to **Settings → API**. This page shows your Client ID, Client Secret, and currently active X-API-Key.
  </Step>

  <Step title="Generate a New X-API-Key">
    Locate the **X-API Key** section and click the **Generate Key** button (highlighted in red). A new key is generated and activated immediately.
  </Step>

  <Step title="Copy the New Key">
    Copy the newly generated X-API-Key from the dashboard and add it to your application configuration or use it directly for testing.
  </Step>
</Steps>

<Warning>
  Clicking **Generate Key** immediately invalidates your existing active X-API-Key. Any running system or integration using the old key will begin receiving `401 Unauthorized` errors the moment you click the button. Only generate a new key from the dashboard when you are ready to update your application configuration simultaneously.
</Warning>

## Using Your X-API-Key in API Requests

Once you have a valid key, include it as a request header on every FastFlowPe API call:

<CodeGroup>
  ```bash cURL theme={"dark"}
  curl --location 'https://api.fastflowpe.com/your-endpoint' \
  --header 'Accept: application/json' \
  --header 'x-api-key: Your-X-API-Key-Here'
  ```

  ```python Python theme={"dark"}
  import requests

  headers = {
      "Accept": "application/json",
      "x-api-key": "Your-X-API-Key-Here",
  }
  response = requests.get("https://api.fastflowpe.com/your-endpoint", headers=headers)
  print(response.json())
  ```

  ```javascript Node.js theme={"dark"}
  const response = await fetch("https://api.fastflowpe.com/your-endpoint", {
    headers: {
      Accept: "application/json",
      "x-api-key": "Your-X-API-Key-Here",
    },
  });
  console.log(await response.json());
  ```

  ```java Java theme={"dark"}
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;

  HttpClient client = HttpClient.newHttpClient();
  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.fastflowpe.com/your-endpoint"))
      .header("Accept", "application/json")
      .header("x-api-key", "Your-X-API-Key-Here")
      .GET()
      .build();
  HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
  System.out.println(response.body());
  ```

  ```go Go theme={"dark"}
  req, _ := http.NewRequest("GET", "https://api.fastflowpe.com/your-endpoint", nil)
  req.Header.Set("Accept", "application/json")
  req.Header.Set("x-api-key", "Your-X-API-Key-Here")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  ```

  ```php PHP theme={"dark"}
  <?php
  $ch = curl_init("https://api.fastflowpe.com/your-endpoint");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      "Accept: application/json",
      "x-api-key: Your-X-API-Key-Here",
  ]);
  $response = curl_exec($ch);
  curl_close($ch);
  echo $response;
  ```

  ```ruby Ruby theme={"dark"}
  require 'net/http'
  require 'uri'

  uri = URI('https://api.fastflowpe.com/your-endpoint')
  request = Net::HTTP::Get.new(uri)
  request['Accept'] = 'application/json'
  request['x-api-key'] = 'Your-X-API-Key-Here'
  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
  puts response.body
  ```
</CodeGroup>

Requests without a valid `x-api-key` header, or with an expired or revoked key, are rejected with a `401 Unauthorized` response.
