
# APIを作成する

`POST /v1/apis` · 権限 `apis:write`

環境内にAPIを作成します。`key`、`identifier`、`name`は必須です。省略したオプションフィールドはデフォルト値を取ります。識別子は環境内で一意です（削除されたAPIはその識別子を90日間予約します）。レスポンスは現在のバージョンを含む`ETag`を含みます。再試行を安全にするには`Idempotency-Key`ヘッダーを送信してください。

## リクエスト

ボディ `application/json`。不明なフィールドは拒否されます。

| フィールド | タイプ | 必須 | 説明 |
|---|---|---|---|
| `key` | string | はい | 安定した設定キー、`^[a-z0-9_-]{1,64}$`。変更不可。 |
| `identifier` | string | はい | トークンオーディエンス: httpsURL（クエリまたはフラグメントなし）または`urn:<nid>:<nss>`。正規形式で保存されます。変更不可。`urn:idp:`ネームスペースは予約されています。 |
| `name` | string | はい | 1～128文字。 |
| `access_token_lifetime_s` | integer | いいえ | 60～86400。デフォルト3600（`mcp_profile`を使用する場合は600）。 |
| `token_format` | string | いいえ | `jwt`（デフォルト）または`opaque`。 |
| `rbac_mode` | string | いいえ | ロールと権限がトークンに反映される方法: `claims`（デフォルト）は`permissions`と`org_permissions`を追加します。`off`はどちらも追加しません（`org_roles`は引き続き追加されます）。`enforce`はそれらを追加し、さらに付与されるスコープをユーザーの有効な権限に制限します。 |
| `allow_offline_access` | boolean | いいえ | デフォルト`true`。 |
| `require_resource_indicator` | boolean | いいえ | デフォルト`false`（`mcp_profile`を使用する場合は`true`）。 |
| `dpop_required` | boolean | いいえ | デフォルト`false`。 |
| `mcp_profile` | boolean | いいえ | httpsの`identifier`と`require_resource_indicator: true`が必要です。 |
| `first_party_access` | string | いいえ | `all`（デフォルト）または`granted_only`。 |
| `introspection_applications` | array | いいえ | このAPIのトークンをイントロスペクトできるアプリケーション(`app_…`)、最大50個、重複なし。同じ環境の`web`および`m2m`アプリケーションのみ。デフォルトは空です。 |

### イントロスペクトアプリケーション

イントロスペクトエンドポイント(`POST <issuer>/oauth2/introspect`、RFC 7662)は、アクセストークンに対して、トークンが発行されたアプリケーション、またはトークンの`aud`で指定されたAPIの`introspection_applications`リストにあるアプリケーションの2つの呼び出し元にのみ`active: true`で応答します。他のすべての呼び出し元は`active: false`を取得するため、APIは互いのトークンを読むことができません。同じ環境の機密アプリケーション(`web`、`m2m`)のみをリストできます。リストはセットとして保存され、ID順で返されます。一時停止されたアプリケーションはリストに残りますが、イントロスペクトはできません。システムAPIのリストは書き込みできません。

## レスポンス

`201 Created`と`ETag`ヘッダー、およびAPI:

```json
{
  "id": "api_01h455vb4pex5vsknk084sn02q",
  "key": "orders",
  "identifier": "https://api.example.com/orders",
  "name": "Orders API",
  "is_system": false,
  "access_token_lifetime_s": 3600,
  "token_format": "jwt",
  "rbac_mode": "claims",
  "allow_offline_access": true,
  "require_resource_indicator": false,
  "dpop_required": false,
  "mcp_profile": false,
  "first_party_access": "all",
  "introspection_applications": ["app_01h455vb4pex5vsknk084sn02r"],
  "created_at": "2026-10-05T12:00:00Z",
  "updated_at": "2026-10-05T12:00:00Z"
}
```

## エラー

| HTTP | code | 情況 |
|---|---|---|
| 400 | `unknown_field` | ボディに上記にリストされていないフィールド（例：`id`または`is_system`）が含まれています。 |
| 409 | `conflict` | 同じ`key`または`identifier`を持つAPIが既に存在します。 |
| 415 | `unsupported_media_type` | コンテンツタイプが`application/json`ではありません。 |
| 422 | `validation_failed` | フィールドが欠落しているか無効です（`errors[].pointer`、例：`/identifier`）。 |
| 422 | `validation_failed` | `introspection_applications`アイテムがこの環境に存在しない(`unknown_application`)、機密ではない(`not_confidential`)、重複している(`duplicate`)、または`app_…` IDではありません(`invalid_value`)。ポインタはリクエスト内のインデックスを名付けます。 |
| 403 | `quota_exceeded` | 環境がその技術的API制限に達しました。 |
| 403 | `insufficient_permissions` | 認証情報に`apis:write`がありません。 |

## 例

```bash
curl -X POST https://api.eu.keenauth.com/v1/apis \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"key":"orders","identifier":"https://api.example.com/orders","name":"Orders API"}'
```
