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 | 예 | 토큰 대상: https URL(쿼리 또는 조각 없음) 또는 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)은 접근 토큰에 대해 두 호출자에게만 active: true로 응답합니다: 토큰이 발급된 애플리케이션 또는 토큰의 aud에 명시된 API의 introspection_applications 목록에 있는 애플리케이션. 다른 모든 호출자는 active: false를 받으므로 API는 서로의 토큰을 읽을 수 없습니다. 동일한 환경의 기밀 애플리케이션(web, m2m)만 나열할 수 있습니다. 목록은 집합으로 저장되고 ID 순서로 반환됩니다. 일시 중단된 애플리케이션은 목록에 남지만 내부검사를 할 수 없습니다. 시스템 API의 목록은 작성할 수 없습니다.
응답
ETag 헤더 및 API가 있는 201 Created:
{
"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가 없습니다. |
예제
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"}'