{"openapi":"3.1.0","info":{"title":"GetMeCentral API","version":"0.1.0","description":"GetMe 生態系統中央控制平台的版本化 API 契約。/openapi.json 是唯一正式介面標準。"},"servers":[{"url":"/","description":"Current GMC instance"}],"tags":[{"name":"System","description":"服務存活與部署就緒檢查"},{"name":"Integration","description":"使用單一 Integration Key 連接 GMC，並換取短效 Service Token"},{"name":"Identity","description":"GMC 使用者帳號、Session、Email Verification 與 Password Reset"},{"name":"Admin","description":"受保護的 GMC 管理介面；僅供伺服器端或受信任管理工具使用"}],"paths":{"/health":{"get":{"operationId":"healthCheck","tags":["System"],"summary":"Check service liveness","responses":{"200":{"description":"Service is alive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/ready":{"get":{"operationId":"readyCheck","tags":["System"],"summary":"Check deployment readiness","responses":{"200":{"description":"Service is ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadyResponse"}}}},"503":{"description":"Required configuration is missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/integration/bootstrap":{"post":{"operationId":"integrationBootstrap","tags":["Integration"],"summary":"Bootstrap a product integration","description":"Validates the server-side GMC Integration Key and returns the product, environment, capabilities, portal pages and usage metrics bound to that key.","security":[{"IntegrationKey":[]}],"responses":{"200":{"description":"Integration metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BootstrapResponse"}}}},"401":{"description":"Invalid integration key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Integration registry is not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/integration/token":{"post":{"operationId":"integrationToken","tags":["Integration"],"summary":"Exchange an Integration Key for a short-lived Service Token","description":"The permanent Integration Key is accepted only at this server-side exchange boundary. Ordinary GMC API calls use the returned short-lived token.","security":[{"IntegrationKey":[]}],"responses":{"200":{"description":"Short-lived Service Token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceTokenResponse"}}}},"401":{"description":"Invalid integration key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/integration/status":{"get":{"operationId":"integrationStatus","tags":["Integration"],"summary":"Read integration health","security":[{"IntegrationKey":[]}],"responses":{"200":{"description":"Integration status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationStatusResponse"}}}},"401":{"description":"Invalid integration key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/auth/register":{"post":{"operationId":"authRegister","tags":["Identity"],"summary":"Register a GMC user","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}}},"responses":{"201":{"description":"User registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"409":{"description":"Email exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/auth/login":{"post":{"operationId":"authLogin","tags":["Identity"],"summary":"Create a GMC user session","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Authenticated session cookie","headers":{"Set-Cookie":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/auth/logout":{"post":{"operationId":"authLogout","tags":["Identity"],"summary":"Revoke the current GMC session","security":[{"UserSession":[]}],"responses":{"200":{"description":"Session revoked","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/auth/me":{"get":{"operationId":"authGetMe","tags":["Identity"],"summary":"Read the current GMC user","security":[{"UserSession":[]}],"responses":{"200":{"description":"Current user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"401":{"description":"Missing or invalid session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/auth/verify-email":{"post":{"operationId":"authVerifyEmail","tags":["Identity"],"summary":"Verify a GMC email token","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"Email verified","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/auth/password-reset/request":{"post":{"operationId":"authRequestPasswordReset","tags":["Identity"],"summary":"Request a password reset","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}}}}},"responses":{"202":{"description":"Request accepted","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/auth/password-reset/confirm":{"post":{"operationId":"authConfirmPasswordReset","tags":["Identity"],"summary":"Reset a password with a one-time token","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetConfirmRequest"}}}},"responses":{"200":{"description":"Password reset","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/organizations":{"get":{"operationId":"organizationList","tags":["Identity"],"security":[{"UserSession":[]}],"responses":{"200":{"description":"Organizations","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"operationId":"organizationCreate","tags":["Identity"],"security":[{"UserSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","slug"],"properties":{"name":{"type":"string"},"slug":{"type":"string"}}}}}},"responses":{"201":{"description":"Organization created","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/organizations/{organizationId}/members":{"get":{"operationId":"organizationListMembers","tags":["Identity"],"security":[{"UserSession":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Memberships","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"operationId":"organizationAddMember","tags":["Identity"],"security":[{"UserSession":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Member added","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/organizations/{organizationId}/members/{membershipId}/role":{"patch":{"operationId":"organizationChangeMemberRole","tags":["Identity"],"security":[{"UserSession":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string"}},{"name":"membershipId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Role updated","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/admin/integrations":{"get":{"operationId":"adminListIntegrations","tags":["Admin"],"summary":"List managed integrations","security":[{"AdminKey":[]}],"responses":{"200":{"description":"Integration list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminIntegrationListResponse"}}}},"401":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"adminCreateIntegration","tags":["Admin"],"summary":"Create an Integration Key","description":"Returns the permanent key exactly once. Do not store or send it to a browser.","security":[{"AdminKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreateIntegrationRequest"}}}},"responses":{"201":{"description":"Integration created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminIntegrationSecretResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/admin/integrations/{integrationId}/rotate":{"post":{"operationId":"adminRotateIntegrationKey","tags":["Admin"],"summary":"Rotate an Integration Key","security":[{"AdminKey":[]}],"parameters":[{"name":"integrationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Replacement key returned once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminIntegrationSecretResponse"}}}},"404":{"description":"Integration not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/admin/integrations/{integrationId}/revoke":{"post":{"operationId":"adminRevokeIntegrationKey","tags":["Admin"],"summary":"Revoke an Integration Key","security":[{"AdminKey":[]}],"parameters":[{"name":"integrationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Integration revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminIntegrationActionResponse"}}}}}}},"/v1/admin/integrations/{integrationId}/status":{"patch":{"operationId":"adminSetIntegrationStatus","tags":["Admin"],"summary":"Enable or disable an Integration","security":[{"AdminKey":[]}],"parameters":[{"name":"integrationId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["active","disabled"]}}}}}},"responses":{"200":{"description":"Integration status changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminIntegrationActionResponse"}}}}}}}},"components":{"securitySchemes":{"IntegrationKey":{"type":"apiKey","in":"header","name":"X-GMC-Integration-Key","description":"永久 Integration Key；只允許伺服器端使用，建立後只顯示一次。"},"AdminKey":{"type":"apiKey","in":"header","name":"X-GMC-Admin-Key","description":"GMC 管理 API Key；不可放進瀏覽器、原始碼或公開設定。"},"UserSession":{"type":"apiKey","in":"cookie","name":"gmc_session","description":"HttpOnly 的 GMC user session cookie。"}},"schemas":{"HealthResponse":{"type":"object","required":["status","service","version"],"properties":{"status":{"const":"ok"},"service":{"const":"getme-central"},"version":{"type":"string"}}},"ReadyResponse":{"type":"object","required":["status","service","checks"],"properties":{"status":{"const":"ready"},"service":{"const":"getme-central"},"checks":{"type":"object","additionalProperties":{"type":"string"}}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string"},"details":{"type":"object"}}}}},"BootstrapResponse":{"type":"object","required":["integration","product","api","capabilities","portal","usage_metrics"],"properties":{"integration":{"type":"object","required":["id","environment","status"],"properties":{"id":{"type":"string"},"environment":{"type":"string","enum":["development","staging","production"]},"status":{"type":"string","enum":["active","disabled","revoked"]}}},"product":{"type":"object","required":["id","code","name"],"properties":{"id":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"}}},"api":{"type":"object","required":["version"],"properties":{"version":{"type":"string","enum":["v1"]}}},"capabilities":{"type":"array","items":{"type":"string"}},"portal":{"type":"object","required":["enabled","pages"],"properties":{"enabled":{"type":"boolean"},"pages":{"type":"array","items":{"type":"string"}}}},"usage_metrics":{"type":"array","items":{"type":"string"}}}},"ServiceTokenResponse":{"type":"object","required":["access_token","token_type","expires_in","expires_at"],"properties":{"access_token":{"type":"string"},"token_type":{"const":"Bearer"},"expires_in":{"type":"integer","minimum":1},"expires_at":{"type":"string","format":"date-time"}}},"IntegrationStatusResponse":{"type":"object","required":["status","integration","webhook"],"properties":{"status":{"type":"string"},"integration":{"type":"object","additionalProperties":true},"webhook":{"type":"object","additionalProperties":true},"last_used_at":{"type":["string","null"],"format":"date-time"},"last_successful_request_at":{"type":["string","null"],"format":"date-time"},"last_error":{"type":["string","null"]}}},"AdminCreateIntegrationRequest":{"type":"object","required":["product","environment","capabilities"],"properties":{"product":{"type":"object","required":["code","name"],"properties":{"code":{"type":"string","pattern":"^[A-Z][A-Z0-9_]*$"},"name":{"type":"string"},"slug":{"type":"string"}}},"environment":{"type":"string","enum":["development","staging","production"]},"capabilities":{"type":"array","minItems":1,"items":{"type":"string"}}}},"AdminIntegrationSecretResponse":{"type":"object","required":["integration","integration_key"],"properties":{"integration":{"type":"object","required":["id","key_id","key_prefix"],"properties":{"id":{"type":"string"},"key_id":{"type":"string"},"key_prefix":{"type":"string"}}},"integration_key":{"type":"string","description":"Only returned at creation or rotation; never persisted in raw form."}}},"AdminIntegrationActionResponse":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string"},"status":{"type":"string"}}},"AdminIntegrationListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","status","product","environment"],"additionalProperties":true}}}},"GMCUser":{"type":"object","required":["id","email","name","status","created_at"],"properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"name":{"type":"string"},"status":{"type":"string","enum":["pending_verification","active","suspended"]},"email_verified_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"UserResponse":{"type":"object","required":["user"],"properties":{"user":{"$ref":"#/components/schemas/GMCUser"},"verification_delivery":{"type":"string","enum":["sent","failed","not_configured"]}}},"RegisterRequest":{"type":"object","required":["email","name","password"],"properties":{"email":{"type":"string","format":"email"},"name":{"type":"string","minLength":2},"password":{"type":"string","minLength":12,"writeOnly":true}}},"LoginRequest":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","writeOnly":true}}},"TokenRequest":{"type":"object","required":["token"],"properties":{"token":{"type":"string","writeOnly":true}}},"PasswordResetConfirmRequest":{"type":"object","required":["token","password"],"properties":{"token":{"type":"string","writeOnly":true},"password":{"type":"string","minLength":12,"writeOnly":true}}}}}}