# API Key for Android Automation: Create, Scope and Rotate

> Create an API key for Android automation in MAS, send it as X-API-KEY or swap it for an MCP token, and handle expiry, scopes, rate limits and revocation.

Source: https://automationmacro.com/docs/api-keys (Integrate, updated 2026-09-09)

An API key lets your own scripts and AI clients drive your Android automation as you, without the desktop app. Macro Automation Studio (MAS) uses one kind of key for two doors: the [REST API](/docs/rest-api) and the [MCP server](/docs/mcp), both of which take the key in an `X-API-Key` header. This page covers creating, using, limiting and retiring keys.

## Before you start

- MAS is installed and you are signed in. Keys are created in the app; there is no other way to mint one.
- Your account has an active subscription or trial. API traffic is refused without one.

## Create a MAS API key

1. In MAS, open **API Keys**.
2. Under **Create a key**, enter a **Name**. It is a label for the list and not part of the secret.
3. Choose **Expires**: **In 30 days**, **In 90 days**, **In 1 year** or **Never**. The default is 90 days.
4. Under **Permissions (scopes)**, tick the capabilities the key may use, or leave every box empty for full access. The scopes are explained below.
5. Click **Create key**.
6. In the **Your new API key** dialog, click **Copy** and store the key somewhere safe, then click **Done**.

The key is `mas_` followed by 48 hexadecimal characters. The server stores only a hash, so the dialog is the only moment you can read the full key. If you close it without copying, revoke the key and create another.

The **Integrations (MCP)** page creates the same kind of key from its **Create an MCP credential** panel. Keys made there never expire and start with `devices:control`, `macros:run` and `maps:read` ticked, which suits a client that drives devices and runs macros.

> [!NOTE]
> The dialog shows a sample `curl` command. Use the host `api.automationmacro.com` for every request, as on the [REST API](/docs/rest-api) page.

## Use the API key in your Android automation

Send the key in an `X-API-KEY` header. Every route that accepts a key resolves it to you, so the response matches what the app would get.

```bash
curl -H "X-API-KEY: mas_your_key" "https://api.automationmacro.com/api/executions?page_size=10"
```

For MCP, send the same header to `https://api.automationmacro.com/mcp` (or `Authorization: Bearer mas_your_key`); the setup for each client is on the [MCP server page](/docs/mcp). Clients that implement the MCP client-credentials extension can instead exchange the key for a one-hour token at `/api/mcp/oauth/token`; the token carries the key's scopes and dies the moment the key is revoked.

## The key list

**Your keys** lists every key, revoked ones included, with its **Name**, the first twelve characters of the **Key**, its **State** (**Active**, **Revoked** or **Expired**), **Last used** and **Expires**. Last used updates on each request that passes the checks below.

## API rate limit and key limits

MAS applies three checks to key traffic. None of them touch the app's own session.

| Check | Limit | Response when exceeded |
|---|---|---|
| Active keys | 25 active keys per account. Revoked and expired keys do not count. | `422` with "You already have 25 active API keys (max 25). Revoke one to create another." |
| Rate limit per key | 120 requests per minute | `429` with `rate_limit_exceeded` and a `Retry-After` header |
| Rate limit per user | 300 requests per minute across all your keys | `429` with `X-RateLimit-Scope: account` |
| Subscription | An active plan or trial | `402` with `subscription_required` |

The rate limit is a fixed one-minute window counted per key and then per account. A `429` carries `Retry-After` in seconds plus `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` (a Unix timestamp) and `X-RateLimit-Scope` (`key` or `account`). Back off until the reset; more keys do not buy more throughput, because the account ceiling covers all of them.

A `402` means the key is valid but its owner has no active subscription or trial. Keys are not deleted when a plan lapses; they start working again when you resubscribe. Plans are on the [pricing page](/pricing) and the mechanics on the [billing page](/docs/billing).

Errors use one envelope:

```json
{"message": "Access Denied", "details": {"code": "invalid_api_key"}}
```

The codes you can see on key traffic are `missing_api_key`, `invalid_api_key` (unknown, revoked or expired), `api_key_not_user_scoped`, `missing_credentials`, `rate_limit_exceeded`, `subscription_required` and `insufficient_scope` (`403`, the key's scopes do not cover the route).

## API key scopes

A key can carry five scopes. You choose them when you create the key, and they cannot be changed afterwards; create a new key for a different set. No scopes ticked means full access.

| Scope | Label in the app | MCP server | REST API |
|---|---|---|---|
| `devices:control` | Control devices | Lease a cloud device, take screenshots, tap, type, read text, find images, read the UI tree, open and close apps, crop and list image-library templates | List devices and device groups |
| `macros:run` | Run macros | List and read your macros; start, check, validate and stop runs; read run logs; create, list and cancel schedules | Start, check and stop cloud runs; read and sync macro code |
| `macros:author` | Author macros | Start, follow, answer and stop a MAS Agent authoring session, which spends AI credits; scaffold and install macro code | none |
| `maps:read` | Read maps | Read the learned menu map of an app | none |
| `runs:read` | Read runs | none | List runs, read one run and its logs |

Scopes are enforced on both doors. An MCP tool call without the right scope returns an error result naming it; a REST route answers `403` with `insufficient_scope`. Routes with no scope of their own (proxies, webhooks, settings profiles) accept full-access keys only: create the key with no boxes ticked. For an AI client, tick the smallest set it needs.

## Rotate an API key

Keys cannot be edited or extended, so rotation means replacing.

1. Create a new key with the same scopes and a fresh expiry.
2. Move your scripts or MCP client to the new key. For MCP, mint a new token from it.
3. Click the revoke icon in the old key's row. The button is labelled **Revoke key** and takes effect at once.

Create the new key before revoking the old one so the switch has no gap. An expired key answers `401` with `invalid_api_key` and shows as **Expired** in the list.

## Revoke a key

Revoke a key the moment you suspect it has leaked. The next request with it gets `401`, on REST and on MCP alike, and any MCP token minted from it stops at the same moment. Revoked keys stay in the list, showing when they were last used, and free a slot toward the 25 active keys.

## Keys are personal

A key always acts as the person who created it: it reads and writes that person's devices, groups, profiles, proxies and webhooks, and its access rides that person's own subscription. Organization scoping is not available through keys.

## Key management needs the app

The routes that list, create and revoke keys (`/api/api-keys`) accept only the app's signed-in session, never a key. A leaked key therefore cannot mint a replacement for itself or extend its own life, so revoking it really ends the compromise. Manage keys on the **API Keys** page.

## Troubleshooting

### 401 invalid_api_key

The key is unknown, revoked or past its expiry, or the header was mistyped. The header name is `X-API-KEY` and the value is the full key including `mas_`. Check the key's **State** in the list and create a new one if it is not **Active**.

### 402 subscription_required

The key is fine, but the account has no active subscription or trial. Open **Subscription** in the app. See [Billing](/docs/billing).

### 429 rate_limit_exceeded

You sent more than 120 requests in a minute with one key, or more than 300 across all keys. Wait for the number of seconds in `Retry-After`, then continue at a lower rate.

### You already have 25 active API keys

The account is at its limit. Revoke a key you no longer use; expired keys already do not count.
