# Users · API keys

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## POST /api-key/create

**Create an API key**

`operationId: ApikeyController_createApiKey`

Creates an API key for machine-to-machine access.

The key value is returned **once, at creation**. It cannot be retrieved afterwards — if it is lost, regenerate rather than hunting for it. Scope the key to what the integration actually needs.

#### Signature

```http
POST /api-key/create (body) -> The created key — the secret is shown only here
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Set an expiry. A key with no expiry outlives whoever created it.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /api-key/regenerate/{keyId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The key to create.

```json
{
  "name": "Warehouse sync",
  "scopes": [
    "storefront:read"
  ],
  "expiresAt": "2027-01-01T00:00:00.000Z"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created key — the secret is shown only here |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /api-key/list

**List my API keys**

`operationId: ApikeyController_getUserApiKeys`

The caller's API keys — names, scopes and last use, but never the secrets.

#### Signature

```http
GET /api-key/list () -> API keys
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /api-key/usage/{keyId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | API keys |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /api-key/{keyId}

**Get an API key**

`operationId: ApikeyController_getApiKey`

Fetches one key's metadata. The secret is not returned.

#### Signature

```http
GET /api-key/{keyId} (keyId: string) -> The key
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `PUT /api-key/{keyId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `keyId` | path | string | yes | API key id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The key |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## PUT /api-key/{keyId}

**Update an API key**

`operationId: ApikeyController_updateApiKey`

Updates a key's name, scopes or expiry. Narrowing scopes takes effect immediately, so check what the integration relies on first.

#### Signature

```http
PUT /api-key/{keyId} (keyId: string, body) -> The updated key
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /api-key/{keyId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `keyId` | path | string | yes | API key id. |

### Request body

Fields to change.

```json
{
  "name": "Warehouse sync (read-only)",
  "scopes": [
    "storefront:read"
  ]
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated key |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /api-key/{keyId}

**Delete an API key**

`operationId: ApikeyController_deleteApiKey`

Deletes a key permanently. Anything using it stops working immediately — check the usage report before deleting a key you did not create.

#### Signature

```http
DELETE /api-key/{keyId} (keyId: string) -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Immediate and irreversible. Check `usage/{keyId}` first.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /api-key/usage/{keyId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `keyId` | path | string | yes | API key id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /api-key/regenerate/{keyId}

**Regenerate an API key**

`operationId: ApikeyController_regenerateApiKey`

Issues a new secret for an existing key and invalidates the old one, keeping the key's name and scopes.

**The old secret stops working the moment this returns.** Have the new value ready to deploy before calling it, or the integration breaks in the gap.

#### Signature

```http
POST /api-key/regenerate/{keyId} (keyId: string) -> The key with its new secret — shown once
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- No overlap period. Plan the cutover before regenerating.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /api-key/create`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `keyId` | path | string | yes | API key id. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The key with its new secret — shown once |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /api-key/usage/{keyId}

**Get API key usage**

`operationId: ApikeyController_getApiKeyUsage`

How a key has been used — request volume and last activity. Read this before revoking a key to see what depends on it, and to spot a key still live long after its integration was retired.

#### Signature

```http
GET /api-key/usage/{keyId} (keyId: string) -> Key usage
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /api-key/{keyId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `keyId` | path | string | yes | API key id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Key usage |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /api-key/admin/list

**List all API keys (admin)**

`operationId: ApikeyController_getAllApiKeys`

Every API key in the organization, not just the caller's — the audit view for finding forgotten or over-scoped keys.

#### Signature

```http
GET /api-key/admin/list () -> All API keys
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Admin`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /api-key/admin/revoke/{keyId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | All API keys |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /api-key/admin/revoke/{keyId}

**Revoke an API key (admin)**

`operationId: ApikeyController_revokeApiKey`

Revokes any key in the organization, regardless of who created it — the response to a leaked credential when its owner is unavailable.

#### Signature

```http
POST /api-key/admin/revoke/{keyId} (keyId: string, body) -> The revoked key
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Admin`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /blacklist/apikey/add`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `keyId` | path | string | yes | API key id. |

### Request body

Optional reason.

```json
{
  "reason": "Leaked in a public repository"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The revoked key |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /api-key/auth

**Authenticate with an API key**

`operationId: ApikeyController_authenticateApiKey`

Exchanges an API key for an access token. The public entry point for machine-to-machine callers — the key is the credential, so it belongs in a header or body, never a URL.

#### Signature

```http
POST /api-key/auth (body) -> An access token
```

#### Access

Public — no credentials required.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `401` | INVALID_KEY | Invalid or revoked API key | The key is unknown, expired, revoked or blacklisted. | Check the key is still active with the usage endpoint. |

Plus the standard platform errors: `429`, `500`.

#### See also

- `POST /validate-app-key`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `x-api-key` | header | string | yes | API Key |

### Request body

The API key.

```json
{
  "key": "ak_9k2m4h1p7q"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | An access token |
| `401` | Invalid or revoked API key — The key is unknown, expired, revoked or blacklisted. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /api-key/org/{orgid}

**List an organization's API keys**

`operationId: ApikeyController_getOrgUsers`

API keys for a named organization. Cross-org, so restrict to operators who legitimately administer more than one tenant.

#### Signature

```http
GET /api-key/org/{orgid} (orgid: string) -> API keys
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /api-key/org/{orgid}/create`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | path | string | yes | Organization id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | API keys |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /api-key/org/{orgid}/create

**Create an API key for an organization**

`operationId: ApikeyController_createOrgUser`

Creates a key against a named organization rather than the caller's own. The secret is returned once.

#### Signature

```http
POST /api-key/org/{orgid}/create (orgid: string, body) -> The created key
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /api-key/org/{orgid}/delete`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | path | string | yes | Organization id. |

### Request body

The key to create.

```json
{
  "name": "Partner integration",
  "scopes": [
    "storefront:read"
  ]
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created key |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /api-key/org/{orgid}/delete

**Delete an organization API key**

`operationId: ApikeyController_deleteOrgUsers`

Deletes a key belonging to a named organization. Note this is a `POST`, not a `DELETE`, unlike the self-service equivalent.

#### Signature

```http
POST /api-key/org/{orgid}/delete (orgid: string, body) -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /api-key/{keyId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | path | string | yes | Organization id. |

### Request body

Which key to delete.

```json
{
  "keyId": "AKY-4821"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Deletion result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

