> ## Documentation Index
> Fetch the complete documentation index at: https://edenai-feat-automate-documentation-tests.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom API Keys

> Custom API keys let you create additional tokens beyond your main account key. Each token can have its own budget, expiration, and type, giving you fine-grained control over access and spending.

export const TechArticleSchema = ({title, description, path, articleSection, about, proficiencyLevel = "Beginner", dependencies, keywords = [], datePublished, dateModified, image, inLanguage = "en"}) => {
  const baseUrl = "https://www.edenai.co/docs";
  const canonicalUrl = `${baseUrl}/${path}`.replace(/\/+$/, "");
  const ogParams = new URLSearchParams({
    division: articleSection || "",
    title: title || "",
    description: description || ""
  });
  const resolvedImage = image || `https://edenai.mintlify.app/_mintlify/api/og?${ogParams.toString()}`;
  const data = {
    "@context": "https://schema.org",
    "@type": "TechArticle",
    "@id": `${canonicalUrl}#techarticle`,
    mainEntityOfPage: {
      "@type": "WebPage",
      "@id": canonicalUrl
    },
    headline: title,
    name: title,
    description: description,
    url: canonicalUrl,
    inLanguage: inLanguage,
    isPartOf: {
      "@type": "WebSite",
      name: "Eden AI Documentation",
      url: baseUrl
    },
    author: [{
      "@type": "Organization",
      name: "Eden AI",
      url: "https://www.edenai.co/"
    }],
    publisher: {
      "@type": "Organization",
      name: "Eden AI",
      url: "https://www.edenai.co/",
      logo: {
        "@type": "ImageObject",
        url: "https://www.edenai.co/assets/logo.png"
      }
    }
  };
  if (articleSection) data.articleSection = articleSection;
  if (about) data.about = {
    "@type": "Thing",
    name: about
  };
  if (proficiencyLevel) data.proficiencyLevel = proficiencyLevel;
  if (dependencies) data.dependencies = dependencies;
  if (keywords && keywords.length) data.keywords = keywords;
  if (datePublished) data.datePublished = datePublished;
  if (dateModified) data.dateModified = dateModified;
  data.image = Array.isArray(resolvedImage) ? resolvedImage : [resolvedImage];
  const json = JSON.stringify(data);
  const schemaId = `techarticle-${canonicalUrl}`;
  React.useEffect(() => {
    if (typeof document === "undefined") return;
    document.querySelectorAll(`script[data-schema-id="${schemaId}"]`).forEach(n => n.remove());
    const script = document.createElement("script");
    script.type = "application/ld+json";
    script.dataset.schemaId = schemaId;
    script.textContent = json;
    document.head.appendChild(script);
    return () => script.remove();
  }, [json, schemaId]);
  return null;
};

<TechArticleSchema title={"Custom API Keys"} description={"Custom API keys let you create additional tokens beyond your main account key. Each token can have its own budget, expiration, and type, giving you fine-grained control over access and spending."} path="v3/general/custom-api-keys" articleSection="General" about={"API Configuration"} proficiencyLevel="Intermediate" keywords={["Eden AI", "AI API", "rate limits", "billing", "monitoring"]} datePublished="2026-05-06T00:00:00Z" dateModified="2026-07-21T00:00:00Z" />

Custom API keys let you create additional tokens beyond your main account key. Each token can have its own budget, expiration, and type, giving you fine-grained control over access and spending.

## Use Cases

* **Environment separation** — dedicated keys for development, staging, and production
* **Team access** — separate keys for different team members or projects
* **Budget control** — set credit limits per key to cap spending
* **Security** — rotate or revoke individual keys without affecting other integrations
* **Usage tracking** — monitor consumption per key

## Token Types

| Type                | Description                        | Use Case                |
| ------------------- | ---------------------------------- | ----------------------- |
| `api_token`         | Production token with full access  | Live applications       |
| `sandbox_api_token` | Test token, no real provider calls | Development and testing |

<Info>
  Sandbox tokens return simulated responses and do not incur any cost. They are ideal for development and CI pipelines.
</Info>

## API Endpoints

| Endpoint                        | Method   | Description          |
| ------------------------------- | -------- | -------------------- |
| `/v2/user/custom_token/`        | `POST`   | Create a new token   |
| `/v2/user/custom_token/`        | `GET`    | List all tokens      |
| `/v2/user/custom_token/{name}/` | `GET`    | Get a specific token |
| `/v2/user/custom_token/{name}/` | `PATCH`  | Update a token       |
| `/v2/user/custom_token/{name}/` | `DELETE` | Delete a token       |

## Create a Token

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api.edenai.run/v2/user/custom_token/",
      headers=headers,
      json={
          "name": "production-v1"
      }
  )

  token = response.json()
  print(f"Created token: {token['name']}")
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.edenai.run/v2/user/custom_token/ \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name": "production-v1"}'
  ```
</CodeGroup>

## Create a Token with Budget

Set a spending limit by enabling `active_balance`:

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api.edenai.run/v2/user/custom_token/",
      headers=headers,
      json={
          "name": "team-backend",
          "token_type": "api_token",
          "balance": "50.00",
          "active_balance": True
      }
  )

  token = response.json()
  print(f"Created token with ${token['balance']} budget")
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.edenai.run/v2/user/custom_token/ \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "team-backend",
      "token_type": "api_token",
      "balance": "50.00",
      "active_balance": true
    }'
  ```
</CodeGroup>

When `active_balance` is `true`, every API call deducts from the token's balance. Once it reaches \$0, the token stops working.

## Periodic Budget Reset

A budget can either **reinitialize automatically** each day, week, or month, or be a **one-time** allowance that stays at \$0 once spent until you top it up manually. You control this with `balance_reset_period` (the reset frequency) and `balance_reset_amount` (the amount the balance is restored to at the start of each period).

### In the dashboard

On the [API Keys](https://app.edenai.run/settings/api-keys) page, create or edit a key and turn on **Spending Limit**. Set the **Reset allowance** (the amount restored each period) and choose a **Resets** frequency — **Daily**, **Weekly**, **Monthly**, or **Never**. A reset frequency is always selected when a spending limit is on; it defaults to **Monthly**. Choose **Never** for a one-time budget that does not renew. A separate **Current balance** field shows what's available right now; editing the allowance only takes effect at the next reset.

### Through the API

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api.edenai.run/v2/user/custom_token/",
      headers=headers,
      json={
          "name": "team-daily",
          "token_type": "api_token",
          "balance_reset_amount": "10.00",
          "balance_reset_period": "daily"
      }
  )
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.edenai.run/v2/user/custom_token/ \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "team-daily",
      "balance_reset_amount": "10.00",
      "balance_reset_period": "daily"
    }'
  ```
</CodeGroup>

| Field                  | Values                               | Meaning                                                                                                                                                                                                          |
| ---------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `balance_reset_period` | `none`, `daily`, `weekly`, `monthly` | How often the balance is restored. `none` = one-time budget; it is the default when the field is omitted from the API request. (The dashboard instead pre-selects **Monthly** when you enable a spending limit.) |
| `balance_reset_amount` | positive amount                      | The value the balance is reset to each period. Required whenever the period is not `none`.                                                                                                                       |

Behaviour to know:

* Setting a reset period **automatically enforces the budget** (`active_balance` becomes `true`) — you don't have to set it separately.
* `balance_reset_amount` is the reset **target**, kept separate from the live `balance` (the amount remaining right now). They are not the same field.
* A new periodic token **starts the period full**: if you don't pass a starting `balance`, it begins at `balance_reset_amount`. Passing an explicit `balance` lets a key start partway through a period.
* Resets run at **midnight Europe/Paris time**: daily every night, weekly on Monday, monthly on the 1st.
* Setting the period back to `none` clears `balance_reset_amount` and returns the token to a one-time budget.

<Note>
  This per-token reset is distinct from the **per-member budget cap** you can set on a [guardrail](/v3/organization/guardrails#budget-cap). A token budget is a hard cap on one key (it stops at \$0); a member budget is a soft periodic spend cap that follows a person across all their keys.
</Note>

## List All Tokens

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY"
  }

  response = requests.get(
      "https://api.edenai.run/v2/user/custom_token/",
      headers=headers
  )

  tokens = response.json()
  for t in tokens:
      print(f"{t['name']} | type: {t['token_type']} | balance: {t['balance']}")
  ```

  ```bash cURL theme={null}
  curl -X GET https://api.edenai.run/v2/user/custom_token/ \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```
</CodeGroup>

## Best Practices

<Tip>
  Use clear naming conventions like `env-project-purpose` (e.g., `prod-billing-api`, `dev-ml-team`) so tokens are easy to identify at a glance.
</Tip>

* **Set budgets on non-production tokens** to prevent accidental overspending during development.
* **Use a periodic reset** (`balance_reset_period`) for recurring allowances — e.g. a \$10/day CI key — instead of topping up manually.
* **Use sandbox tokens for CI/CD** to validate integrations without incurring costs.
* **Rotate tokens periodically** — create a new token, migrate your application, then delete the old one.
* **Set expiration dates** on temporary tokens (e.g., for contractors or short-term projects).
