# API Keys Management

Manage merchant API keys for authentication.

All endpoints require `Authorization: Bearer <JWT>`. Tenant admins can manage keys for any merchant in the tenant; merchant users can only manage keys of their own merchant and its locations (keys outside that scope return `404`).

---

## Key Types

| `keyType` | Prefix | Scope | Use |
|-----------|--------|-------|-----|
| `standard` (default) | `api-` | Merchant | Server-side REST integrations and the WooCommerce plugin |
| `sdk_public` | `lpk_live_` | Merchant | Browser embed key for `auxVault.js` checkout only — not for plugins or servers; origin allow-list (optional here, required by the dashboard) |
| `processing` | `lv_pk_` | Merchant | Payment operations for one merchant gateway (`gatewayId`) |
| `token_processing` | `ltk_` | Merchant | Server-side PCI token processing; requires an IP allow-list |
| `erp` | `lv_erp_` | Tenant | Tenant-wide ERP integration; pass `X-Merchant-ID` per request |

Merchant users may create only `standard` and `sdk_public` keys. The other types, and any tenant-scoped key, require an administrator (`403` otherwise).

---

## Create API Key

```http
POST /api/v1/api-keys
```

```bash
curl -X POST https://uat.auxcore.net/api/v1/api-keys \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantId": "8f3c2a1e-5b7d-4e9a-9c1f-2d6e8a4b7c30",
    "name": "Production Key",
    "keyType": "standard",
    "expiresInDays": 365
  }'
```

**Request Body:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Display name |
| `merchantId` | uuid | Yes for merchant-scoped keys | Merchant the key belongs to |
| `keyType` | enum | No | `standard` (default), `sdk_public`, `processing`, `token_processing`, `erp` |
| `scope` | enum | No | `merchant` (default) or `tenant`. `erp` keys are always `tenant`. |
| `description` | string | No | |
| `expiresInDays` | number | No | Key expires this many days after creation. Omit for no expiry. |
| `allowedOrigins` | string[] | No | `sdk_public` only. Origins allowed to use the key, e.g. `https://shop.example.com`. Empty = any origin. |
| `allowedServerIps` | string[] | `token_processing` only | Static egress IPs allowed to call the vault. At least one is required. |
| `gatewayId` | uuid | No | `processing` only: the merchant gateway the key is bound to |
| `permissions` | string[] | No | Stored with the key. Not currently enforced by the API gateway. |

**Response (201 Created):**

```json
{
  "success": true,
  "data": {
    "apiKey": {
      "id": "5e8b1c3d-9a2f-4d7e-b6c0-1f4a8e2d9b57",
      "tenantId": "your-tenant-id",
      "merchantId": "8f3c2a1e-5b7d-4e9a-9c1f-2d6e8a4b7c30",
      "scope": "merchant",
      "keyType": "standard",
      "keyPrefix": "api-Xk3mP9qL",
      "name": "Production Key",
      "isActive": true,
      "expiresAt": "2027-01-28T12:00:00.000Z",
      "createdAt": "2026-01-28T12:00:00.000Z"
    },
    "plainKey": "api-Xk3mP9qLr2Tw8Vn4Bz6Yc1Hd5Fj"
  }
}
```

⚠️ **Save this key!** `plainKey` is only returned on creation (and on regenerate). Only `sdk_public` keys can be shown again later, because they are meant to be public.

---

## List API Keys

```http
GET /api/v1/api-keys
```

| Query | Default | Description |
|-------|---------|-------------|
| `merchantId` | caller's merchant | Filter to one merchant (must be in the caller's scope) |
| `includeLocations` | `false` | `true` also returns keys of the caller's locations |
| `keyType` | — | Filter by key type |
| `gatewayId` | — | Filter by gateway |
| `isActive` | — | `true` / `false` |
| `page` | `1` | |
| `limit` | `50` | |

**Response:** `{ "success": true, "data": [ ... ], "meta": { "page": 1, "limit": 50, "total": 3 } }`. Each key includes a `maskedKey` such as `api-Xk3mP9qL••••••••••••`; the secret is never returned.

---

## Get API Key

```http
GET /api/v1/api-keys/:keyId
```

---

## Update API Key

```http
PATCH /api/v1/api-keys/:keyId
```

```json
{
  "name": "Storefront SDK key",
  "allowedOrigins": ["https://shop.example.com", "https://www.example.com"]
}
```

- `name`: non-empty, max 255 characters. `description`: max 1000 characters.
- `allowedOrigins` applies to `sdk_public` keys only; values are lower-cased and trailing slashes removed.
- `allowedServerIps` applies to `token_processing` keys only and cannot be empty.

---

## Regenerate API Key

```http
POST /api/v1/api-keys/:keyId/regenerate
```

Issues a new secret with the same prefix type; the old secret stops working immediately. Returns `{ apiKey, plainKey }`.

---

## Disable API Key

```http
POST /api/v1/api-keys/:keyId/disable
```

`POST /api/v1/api-keys/:keyId/enable` re-enables it.

---

## Revoke API Key

```http
DELETE /api/v1/api-keys/:keyId
```

Permanently revokes (soft-deletes) the key. Returns `{ "success": true, "data": { "message": "API key deleted successfully" } }`.

---

## Using SDK Public Keys

When an `sdk_public` key has `allowedOrigins`, every request must send an `Origin` or `X-Merchant-Origin` header that matches the list; otherwise the API returns `403` (`Origin required` / `Origin not allowed`). These keys are rejected on admin and internal paths. Use a `standard` key for server-to-server calls.

---

**Need help?** Contact support@auxcore.net
