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

# Rotate API Key

> Rotate your Data App API key to enhance security and manage key lifecycle effectively.

Rotate your data app API key to maintain security best practices by periodically refreshing credentials. This endpoint expires the current API key and generates a new one, ensuring seamless transition while maintaining security.

<Note>
  The API key used in the `Authorization` header **is** the key being rotated. You only need to provide `expireAt` in the request body — no `key` field required.
</Note>

## Authentication

This endpoint requires the **data app API key** you want to rotate in the `Authorization` header. The key used for authentication is the key that will be expired and replaced with a new one.

To access your data app API key:

1. Go to your Databrain dashboard and open the **Data Apps** section.
2. Select the data app whose API key you want to rotate.
3. Find the **API Key** under the data app settings.

Use this key as the Bearer value in your Authorization header.

## Headers

<ParamField header="Authorization" type="string" required>
  Bearer token for API authentication. Use the **data app API key** you want to rotate.

  ```
  Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000
  ```
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be set to `application/json` for all requests.

  ```
  Content-Type: application/json
  ```
</ParamField>

## Request Body

<ParamField body="expireAt" type="number | string" required>
  Duration in seconds until the current API key expires. This allows for a grace period to update your applications before the old key stops working. Accepts a number or a numeric string.

  <Expandable title="Common expiration durations">
    * `0` - Expire immediately (instant rotation)
    * `300` - 5 minutes
    * `3600` - 1 hour
    * `86400` - 24 hours
    * `604800` - 7 days

    **Recommended:** Set a grace period (e.g., `3600`) to allow time for updating your applications without service interruption.
  </Expandable>
</ParamField>

## Response

<ResponseField name="key" type="string">
  The newly generated API key (UUID format). Use this key for all future API requests.
</ResponseField>

<ResponseField name="error" type="object">
  Error object returned only when the request fails. Not included in successful responses.

  <Expandable title="error properties">
    <ResponseField name="code" type="string">
      Error code identifying the type of error.
    </ResponseField>

    <ResponseField name="message" type="string">
      Human-readable error message describing what went wrong.
    </ResponseField>
  </Expandable>
</ResponseField>

## Examples

<Panel>
  <RequestExample>
    ```bash cURL - Immediate Rotation theme={"dark"}
    curl --request POST \
      --url https://api.usedatabrain.com/api/v2/data-app/rotate-api \
      --header 'Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000' \
      --header 'Content-Type: application/json' \
      --data '{
        "expireAt": 0
      }'
    ```

    ```bash cURL - Rotation with Grace Period theme={"dark"}
    curl --request POST \
      --url https://api.usedatabrain.com/api/v2/data-app/rotate-api \
      --header 'Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000' \
      --header 'Content-Type: application/json' \
      --data '{
        "expireAt": 3600
      }'
    ```

    ```javascript Node.js theme={"dark"}
    const response = await fetch('https://api.usedatabrain.com/api/v2/data-app/rotate-api', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer 550e8400-e29b-41d4-a716-446655440000',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        expireAt: 3600
      })
    });

    const data = await response.json();
    console.log('New API Key:', data.key);
    ```

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

    response = requests.post(
        'https://api.usedatabrain.com/api/v2/data-app/rotate-api',
        headers={
            'Authorization': 'Bearer 550e8400-e29b-41d4-a716-446655440000',
            'Content-Type': 'application/json'
        },
        json={
            'expireAt': 3600
        }
    )

    data = response.json()
    print('New API Key:', data['key'])
    ```

    ```java Java theme={"dark"}
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    import java.net.URI;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.util.Map;

    HttpClient client = HttpClient.newHttpClient();
    ObjectMapper mapper = new ObjectMapper();

    Map<String, Object> requestBody = Map.of(
        "expireAt", 3600
    );

    HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://api.usedatabrain.com/api/v2/data-app/rotate-api"))
        .header("Authorization", "Bearer 550e8400-e29b-41d4-a716-446655440000")
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(requestBody)))
        .build();

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

    ```php PHP theme={"dark"}
    <?php
    $curl = curl_init();

    $data = [
        'expireAt' => 3600
    ];

    curl_setopt_array($curl, [
        CURLOPT_URL => 'https://api.usedatabrain.com/api/v2/data-app/rotate-api',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_POSTFIELDS => json_encode($data),
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000',
            'Content-Type: application/json'
        ],
    ]);

    $response = curl_exec($curl);
    curl_close($curl);

    $result = json_decode($response, true);
    echo 'New API Key: ' . $result['key'];
    ?>
    ```

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

    uri = URI('https://api.usedatabrain.com/api/v2/data-app/rotate-api')
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true

    request = Net::HTTP::Post.new(uri)
    request['Authorization'] = 'Bearer 550e8400-e29b-41d4-a716-446655440000'
    request['Content-Type'] = 'application/json'

    request.body = {
      expireAt: 3600
    }.to_json

    response = http.request(request)
    result = JSON.parse(response.body)
    puts "New API Key: #{result['key']}"
    ```

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

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

    type RotateKeyRequest struct {
        ExpireAt int `json:"expireAt"`
    }

    type RotateKeyResponse struct {
        Key string `json:"key"`
    }

    func main() {
        requestBody := RotateKeyRequest{
            ExpireAt: 3600,
        }

        jsonData, _ := json.Marshal(requestBody)

        req, _ := http.NewRequest("POST", "https://api.usedatabrain.com/api/v2/data-app/rotate-api", bytes.NewBuffer(jsonData))
        req.Header.Set("Authorization", "Bearer 550e8400-e29b-41d4-a716-446655440000")
        req.Header.Set("Content-Type", "application/json")

        client := &http.Client{}
        resp, _ := client.Do(req)
        defer resp.Body.Close()

        var result RotateKeyResponse
        json.NewDecoder(resp.Body).Decode(&result)
        fmt.Printf("New API Key: %s\n", result.Key)
    }
    ```

    ```csharp C# theme={"dark"}
    using System;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using Newtonsoft.Json;

    public class RotateKeyRequest
    {
        [JsonProperty("expireAt")]
        public int ExpireAt { get; set; }
    }

    public class RotateKeyResponse
    {
        [JsonProperty("key")]
        public string Key { get; set; }
    }

    var client = new HttpClient();
    var request = new RotateKeyRequest { ExpireAt = 3600 };

    var json = JsonConvert.SerializeObject(request);
    var content = new StringContent(json, Encoding.UTF8, "application/json");

    client.DefaultRequestHeaders.Add("Authorization", "Bearer 550e8400-e29b-41d4-a716-446655440000");
    var response = await client.PostAsync("https://api.usedatabrain.com/api/v2/data-app/rotate-api", content);

    var result = JsonConvert.DeserializeObject<RotateKeyResponse>(await response.Content.ReadAsStringAsync());
    Console.WriteLine($"New API Key: {result.Key}");
    ```
  </RequestExample>

  <ResponseExample>
    ```json 200 - Success theme={"dark"}
    {
      "key": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
    }
    ```

    ```json 400 - Invalid Request Body theme={"dark"}
    {
      "error": {
        "code": "INVALID_REQUEST_BODY",
        "message": "\"expireAt\" is required"
      }
    }
    ```

    ```json 400 - Invalid API Key Format theme={"dark"}
    {
      "error": {
        "code": "AUTHENTICATION_ERROR",
        "message": "API Key is not provided or Invalid!"
      }
    }
    ```

    ```json 401 - API Key Not Found or Expired theme={"dark"}
    {
      "error": {
        "code": "AUTHENTICATION_ERROR",
        "message": "API Key is invalid or expired!"
      }
    }
    ```

    ```json 400 - Not a Data App API Key theme={"dark"}
    {
      "error": {
        "code": "INVALID_DATA_APP_API_KEY",
        "message": "invalid or expired API KEY, data app not found"
      }
    }
    ```

    ```json 500 - Internal Server Error theme={"dark"}
    {
      "error": {
        "code": "INTERNAL_SERVER_ERROR",
        "message": "INTERNAL_SERVER_ERROR"
      }
    }
    ```
  </ResponseExample>
</Panel>

## HTTP Status Code Summary

| Status Code | Description                                                       |
| ----------- | ----------------------------------------------------------------- |
| `200`       | **OK** - Key rotated successfully                                 |
| `400`       | **Bad Request** - Invalid request parameters or invalid key state |
| `401`       | **Unauthorized** - API key not found in DB or already expired     |
| `500`       | **Internal Server Error** - Server error occurred                 |

## Possible Errors

| Error Code                 | HTTP Status | Description                                                                                                                     |
| -------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `INVALID_REQUEST_BODY`     | 400         | Missing or invalid `expireAt` parameter                                                                                         |
| `AUTHENTICATION_ERROR`     | 400 / 401   | API key missing or not a valid UUID (400); or not found / already expired in DB (401)                                           |
| `INVALID_DATA_APP_API_KEY` | 400         | Token is a service token (no `dataAppId`), key not found, belongs to a different org, or the key already has an expiry date set |
| `INTERNAL_SERVER_ERROR`    | 500         | Server error                                                                                                                    |

## Related Resources

<CardGroup cols={2}>
  <Card title="API Token Guide" icon="key" href="/developer-docs/helpers/api-token">
    Learn about API token management and authentication
  </Card>

  <Card title="Create Data App" icon="database" href="/guides/datasources/create-a-data-app">
    Create data apps and generate initial API tokens
  </Card>

  <Card title="Guest Token API" icon="ticket" href="/developer-docs/helpers/api-reference/token">
    Generate guest tokens using your data app API key
  </Card>

  <Card title="List Embeds API" icon="list" href="/developer-docs/helpers/api-reference/list-embed">
    List all embed configurations for your data app
  </Card>
</CardGroup>
