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

# Temporary Keys

> Create temporary API keys that automatically expire after a set duration. Use expiring keys for trials, short-lived sessions, or demos.

Temporary keys automatically become invalid after a specified time. No cleanup required, Unkey handles expiration and deletion for you.

## When to use this

<CardGroup cols={2}>
  <Card title="Trial access" icon="clock">
    Give new users a 7-day trial key. It stops working automatically.
  </Card>

  <Card title="Time-limited integrations" icon="link">
    Partner needs API access for a project? Key expires when the project ends.
  </Card>

  <Card title="Session-based access" icon="right-from-bracket">
    Generate a key that lasts for a user's session (e.g., 24 hours).
  </Card>

  <Card title="Security rotations" icon="arrows-rotate">
    Force key rotation by having keys expire periodically.
  </Card>
</CardGroup>

## How it works

1. Create a key with an `expires` timestamp (Unix milliseconds)
2. Key works normally until the expiration time
3. After expiration, verification returns `code: EXPIRED`
4. Unkey automatically cleans up expired keys

## Create a temporary key

Set `expires` to a Unix timestamp in **milliseconds**:

<CodeGroup>
  ```bash cURL theme={"theme":"kanagawa-wave"}
  # Key expires in 24 hours
  EXPIRES=$(($(date +%s) * 1000 + 86400000))

  curl -X POST https://api.unkey.com/v2/keys.createKey \
    -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "apiId": "api_...",
      "expires": '$EXPIRES'
    }'
  ```

  ```typescript TypeScript theme={"theme":"kanagawa-wave"}
  // Key expires in 24 hours
  const expires = Date.now() + 24 * 60 * 60 * 1000;

  try {
    const { meta, data } = await unkey.keys.createKey({
      apiId: "api_...",
      expires,
    });
  } catch (err) {
    console.error(err);
    return Response.json({ error: "Internal error" }, { status: 500 });
  }
  ```

  ```python Python theme={"theme":"kanagawa-wave"}
  import time

  # Key expires in 24 hours
  expires = int(time.time() * 1000) + (24 * 60 * 60 * 1000)

  result = unkey.keys.create_key(
      api_id="api_...",
      expires=expires
  )
  ```
</CodeGroup>

## Common expiration times

| Duration      | Calculation                             |
| ------------- | --------------------------------------- |
| 1 hour        | `Date.now() + 60 * 60 * 1000`           |
| 24 hours      | `Date.now() + 24 * 60 * 60 * 1000`      |
| 7 days        | `Date.now() + 7 * 24 * 60 * 60 * 1000`  |
| 30 days       | `Date.now() + 30 * 24 * 60 * 60 * 1000` |
| Specific date | `new Date("2024-12-31").getTime()`      |

## Verification response

When verifying an expired key:

```json theme={"theme":"kanagawa-wave"}
{
  "meta": { "requestId": "req_..." },
  "data": {
    "valid": false,
    "code": "EXPIRED",
    "keyId": "key_..."
  }
}
```

## Extend or change expiration

Update the expiration time on an existing key:

<CodeGroup>
  ```bash cURL theme={"theme":"kanagawa-wave"}
  # Extend by 7 more days from now
  EXPIRES=$(($(date +%s) * 1000 + 604800000))

  curl -X POST https://api.unkey.com/v2/keys.updateKey \
    -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "keyId": "key_...",
      "expires": '$EXPIRES'
    }'
  ```

  ```typescript TypeScript theme={"theme":"kanagawa-wave"}
  // Extend by 7 more days from now
  try {
    const { meta, data } = await unkey.keys.updateKey({
      keyId: "key_...",
      expires: Date.now() + 7 * 24 * 60 * 60 * 1000,
    });
  } catch (err) {
    console.error(err);
    return Response.json({ error: "Internal error" }, { status: 500 });
  }
  ```
</CodeGroup>

## Remove expiration

Make a temporary key permanent by setting `expires` to `null`:

```bash theme={"theme":"kanagawa-wave"}
curl -X POST https://api.unkey.com/v2/keys.updateKey \
  -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "keyId": "key_...",
    "expires": null
  }'
```

## Combining with other features

Temporary keys work with all other key features:

```typescript theme={"theme":"kanagawa-wave"}
// 7-day trial with 1000 requests and rate limiting
try {
  const { meta, data } = await unkey.keys.createKey({
    apiId: "api_...",
    expires: Date.now() + 7 * 24 * 60 * 60 * 1000,
    credits: {
      remaining: 1000,
    },
    ratelimits: [
      {
        name: "requests",
        limit: 100,
        duration: 60000, // 100 per minute
      },
    ],
  });
} catch (err) {
  console.error(err);
  return Response.json({ error: "Internal error" }, { status: 500 });
}
```

## Temporary vs usage-limited keys

| Feature       | Temporary Keys       | Usage-Limited Keys    |
| ------------- | -------------------- | --------------------- |
| Controlled by | Time                 | Request count         |
| Expires when  | Clock hits timestamp | Credits reach 0       |
| Good for      | Time-bound access    | Pay-per-use, quotas   |
| Example       | "Access for 7 days"  | "1000 requests total" |

**Use both together** for trial limits: "7 days OR 1000 requests, whichever comes first."

## Next steps

<CardGroup cols={2}>
  <Card title="Usage limits" icon="calculator" href="/platform/apis/features/remaining">
    Cap total requests per key
  </Card>

  <Card title="Key rotation" icon="arrows-rotate" href="/platform/apis/features/rerolling-key">
    Generate new keys while maintaining config
  </Card>
</CardGroup>
