> For the complete documentation index, see [llms.txt](https://docs.flxbl.io/flxbl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flxbl.io/flxbl/sfp-server/api-reference/integrations.md).

# Integrations

## List all integrations

> List all configured integrations. Returns integration metadata without credentials.\
> \
> \*\*Authentication\*\*: Requires Owner role. This endpoint is for administrative purposes to view and manage integrations.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/integrations":{"get":{"operationId":"IntegrationsController_list","summary":"List all integrations","description":"List all configured integrations. Returns integration metadata without credentials.\n\n**Authentication**: Requires Owner role. This endpoint is for administrative purposes to view and manage integrations.","parameters":[{"name":"provider","required":false,"in":"query","description":"Filter by provider: `github` or `jira`","schema":{"enum":["github","azuredevops","jfrog","gitlab","npm","github_packages","jira","azure-devops","servicenow","ai_anthropic","ai_openai","ai_google","ai_github_copilot","ai_amazon_bedrock","ai_google_vertex","datadog","newrelic","splunk","browserbase","slack","teams"],"type":"string"}}],"responses":{"200":{"description":"List of integrations"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Requires role: owner"}},"tags":["Integrations"]}}}}
```

## Store credentials for external services (Jira, GitHub)

> Securely store credentials for external integrations. Credentials are encrypted at rest using AES-256.\
> \
> \*\*Authentication\*\*: Requires Owner role. Application tokens are not permitted for credential creation.\
> \
> \*\*Scope options:\*\*\
> \- \*\*Global\*\* (\`isGlobal: true\`): Credentials available to all projects. Use for shared services like a company-wide Jira.\
> \- \*\*Project-scoped\*\* (\`projects: \[...]\`): Credentials only for specific repositories. Projects must be registered first via \`POST /projects\`.\
> \
> \*\*Common setups:\*\*\
> \- Jira: \`provider: "jira", authType: "basic\_auth", credentials: { base\_url, username, api\_token }\`\
> \- GitHub PAT: \`provider: "github", authType: "pat", credentials: { token }\`\
> \
> See full guide: <https://docs.flxbl.io/sfp/api-reference/integrations>

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"CreateIntegrationDto":{"type":"object","properties":{"provider":{"$ref":"#/components/schemas/IntegrationProvider"},"authType":{"$ref":"#/components/schemas/IntegrationAuthType"},"credentials":{"type":"object","description":"Provider-specific credentials. Examples:\n        - GitHub PAT: { token: \"ghp_xxx\" }\n        - GitHub App: { appId: \"123456\", privateKey: \"-----BEGIN RSA...\" }\n        - GitHub OAuth App: { client_id: \"Iv1.xxx\", client_secret: \"xxx\" }\n        - Azure DevOps PAT: { organization_url: \"https://dev.azure.com/org\", token: \"xxx\" }\n        - Azure DevOps Service Principal: { organization_url: \"https://dev.azure.com/org\", client_id: \"xxx\", client_secret: \"xxx\", tenant_id: \"xxx\", entra_authority_url: \"https://login.microsoftonline.com\" }\n        - Jira basic_auth: { base_url: \"https://company.atlassian.net\", username: \"email\", api_token: \"token\" }\n        - Jira oauth_client_credentials: { client_id: \"...\", client_secret: \"...\", cloud_id: \"...\" }\n        - AI Anthropic: { api_key: \"sk-ant-...\" }\n        - AI OpenAI: { api_key: \"sk-...\" }\n        - AI Google: { api_key: \"...\" }\n        - AI GitHub Copilot: { token: \"ghu_...\" }\n        - AI Amazon Bedrock: { bearer_token: \"...\", region: \"us-east-1\" }\n        - AI Google Vertex: { project: \"my-project-123456\", location: \"us\", service_account_json: \"{ ... }\" }\n        - DataDog: { api_key: \"dd-xxx\" }  (config: { site: \"datadoghq.com\" })\n        - New Relic: { api_key: \"NRAK-xxx\" }  (config: { region: \"US\" })\n        - Splunk: { api_key: \"splunk-hec-token\" }  (config: { host: \"https://input-prd-xxx.cloud.splunk.com:8088\" })\n        - Teams webhook: { webhook_url: \"https://...\" }"},"projects":{"description":"Repository identifiers to scope this integration to. Get these from `GET /projects` or register via `POST /projects`. Required if `isGlobal` is false.","type":"array","items":{"type":"string"}},"isGlobal":{"type":"boolean","description":"Set `true` to make credentials available to ALL projects. Use for shared services like a company-wide Jira instance. Either `isGlobal` or `projects` must be specified."},"isDefault":{"type":"boolean","description":"Mark as the system default for this provider category. Only global integrations can be default. AI providers are grouped — setting one AI provider as default unsets any other AI default.","default":false},"config":{"type":"object","description":"Provider-specific configuration options"}},"required":["provider","authType","credentials"]},"IntegrationProvider":{"type":"string","description":"External service to integrate with","default":"github","enum":["github","azuredevops","jfrog","gitlab","npm","github_packages","jira","azure-devops","servicenow","ai_anthropic","ai_openai","ai_google","ai_github_copilot","ai_amazon_bedrock","ai_google_vertex","datadog","newrelic","splunk","browserbase","slack","teams"]},"IntegrationAuthType":{"type":"string","description":"How to authenticate with the provider:\n- `pat` for GitHub/Azure DevOps tokens\n- `basic_auth` for Jira (email + API token)\n- `oauth_client_credentials` for Jira OAuth 2.0 (client_id + client_secret + cloud_id)\n- `service_principal` for Azure DevOps (client_id + client_secret + tenant_id)\n- `app` for GitHub App\n- `oauth` for OAuth flows\n- `api_key` for AI providers (Anthropic, OpenAI, Google)\n- `bearer` for AWS Bedrock\n- `service_account` for Claude on Google Vertex (project + location + service account JSON)","default":"pat","enum":["pat","oauth","app","basic","basic_auth","oauth_client_credentials","service_principal","api_key","bearer","service_account","slack_webhook","teams_webhook"]}}},"paths":{"/sfp/api/integrations":{"post":{"operationId":"IntegrationsController_create","summary":"Store credentials for external services (Jira, GitHub)","description":"Securely store credentials for external integrations. Credentials are encrypted at rest using AES-256.\n\n**Authentication**: Requires Owner role. Application tokens are not permitted for credential creation.\n\n**Scope options:**\n- **Global** (`isGlobal: true`): Credentials available to all projects. Use for shared services like a company-wide Jira.\n- **Project-scoped** (`projects: [...]`): Credentials only for specific repositories. Projects must be registered first via `POST /projects`.\n\n**Common setups:**\n- Jira: `provider: \"jira\", authType: \"basic_auth\", credentials: { base_url, username, api_token }`\n- GitHub PAT: `provider: \"github\", authType: \"pat\", credentials: { token }`\n\nSee full guide: https://docs.flxbl.io/sfp/api-reference/integrations","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIntegrationDto"}}}},"responses":{"201":{"description":"Integration created successfully"},"400":{"description":"Invalid configuration, missing scope (isGlobal or projects), or project not found"},"401":{"description":"Application tokens not permitted - requires user authentication"},"403":{"description":"Forbidden - Requires role: owner"}},"tags":["Integrations"]}}}}
```

## Open a test ServiceNow change request

> Create a real ServiceNow change request using the configured ServiceNow credentials for a project and a mock sfp release payload. Returns only sanitized change-request identifiers and a ServiceNow UI link; stored credentials are never returned.\
> \
> \*\*Authentication\*\*: Requires Owner role.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"TestServiceNowChangeRequestDto":{"type":"object","properties":{"repositoryIdentifier":{"type":"string","description":"Project repository identifier (owner/repo)"},"releaseCandidate":{"type":"string","description":"Mock release candidate name to include in the test change request."},"environments":{"description":"Mock target environment names to include in the test change request.","type":"array","items":{"type":"string"}},"shortDescription":{"type":"string","description":"Override the ServiceNow short_description used for the test change request."},"description":{"type":"string","description":"Override the ServiceNow description used for the test change request."},"correlationId":{"type":"string","description":"Override the generated correlation_id. Omit this to create a new test CR each time."},"fields":{"type":"object","description":"Additional ServiceNow change_request fields for the mock payload. Values must be strings."}},"required":["repositoryIdentifier"]}}},"paths":{"/sfp/api/integrations/servicenow/change-requests/test":{"post":{"operationId":"IntegrationsController_testServiceNowChangeRequest","summary":"Open a test ServiceNow change request","description":"Create a real ServiceNow change request using the configured ServiceNow credentials for a project and a mock sfp release payload. Returns only sanitized change-request identifiers and a ServiceNow UI link; stored credentials are never returned.\n\n**Authentication**: Requires Owner role.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestServiceNowChangeRequestDto"}}}},"responses":{"201":{"description":"Test change request created successfully"},"400":{"description":"ServiceNow integration credentials are missing or the mock payload is invalid"},"403":{"description":"Forbidden - Requires role: owner"},"502":{"description":"ServiceNow rejected or failed the test change request"}},"tags":["Integrations"]}}}}
```

## List default integrations

> List all integrations marked as system defaults. One default per provider category (AI providers are grouped — only one default across all AI providers). Default integrations are used as fallback when a project has no project-specific integration.\
> \
> \*\*Authentication\*\*: Requires Owner role.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/integrations/defaults":{"get":{"operationId":"IntegrationsController_listDefaults","summary":"List default integrations","description":"List all integrations marked as system defaults. One default per provider category (AI providers are grouped — only one default across all AI providers). Default integrations are used as fallback when a project has no project-specific integration.\n\n**Authentication**: Requires Owner role.","parameters":[],"responses":{"200":{"description":"List of default integrations"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Requires role: owner"}},"tags":["Integrations"]}}}}
```

## Retrieve stored credentials

> Fetch decrypted credentials for integrations. Returns credentials matching the filter criteria. All access is logged for audit purposes.\
> \
> \*\*Authentication\*\*: Requires Owner role or Application token. Application tokens must specify a \`provider\` or \`project\` filter to prevent unscoped credential enumeration.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/integrations/credentials":{"get":{"operationId":"IntegrationsController_getCredentials","summary":"Retrieve stored credentials","description":"Fetch decrypted credentials for integrations. Returns credentials matching the filter criteria. All access is logged for audit purposes.\n\n**Authentication**: Requires Owner role or Application token. Application tokens must specify a `provider` or `project` filter to prevent unscoped credential enumeration.","parameters":[{"name":"provider","required":false,"in":"query","description":"Filter by service: `github` or `jira`","schema":{"enum":["github","azuredevops","jfrog","gitlab","npm","github_packages","jira","azure-devops","servicenow","ai_anthropic","ai_openai","ai_google","ai_github_copilot","ai_amazon_bedrock","ai_google_vertex","datadog","newrelic","splunk","browserbase","slack","teams"],"type":"string"}},{"name":"project","required":false,"in":"query","description":"Filter by registered project identifier (e.g., `flxbl-io/sf-core`). List projects via `GET /projects`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Credentials retrieved successfully"},"403":{"description":"Forbidden - Requires role: owner, application"},"404":{"description":"No integration found for the specified filters"}},"tags":["Integrations"]}}}}
```

## List approved AI models per provider

> The manually-maintained APPROVED model catalog, per AI provider, in each provider's own model-id format. Newest first — the first entry is the provider's automatic default. Feeds the AI integration card's model chooser.\
> \
> \*\*Authentication\*\*: Requires Owner role (same audience as the integration forms).

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/integrations/ai/models":{"get":{"operationId":"IntegrationsController_approvedAiModels","summary":"List approved AI models per provider","description":"The manually-maintained APPROVED model catalog, per AI provider, in each provider's own model-id format. Newest first — the first entry is the provider's automatic default. Feeds the AI integration card's model chooser.\n\n**Authentication**: Requires Owner role (same audience as the integration forms).","parameters":[],"responses":{"200":{"description":"Approved models keyed by provider id"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Requires role: owner"}},"tags":["Integrations"]}}}}
```

## Resolve cherry-to target and AI availability policy

> Returns a non-secret, deterministic policy result for the cherry-to CLI. Credential material is never included; application callers retrieve the selected integration through the audited credentials endpoint.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"CherryToPolicyResponseDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether cherry-to is configured and has a usable, supported AI integration"},"targetAllowed":{"type":"boolean","description":"Whether the supplied target matches the project cherry-to target policy"},"status":{"type":"string","enum":["available","disabled","unavailable"]},"reason":{"type":"string","enum":["cherry_to_not_configured","target_not_allowed","ai_disabled","ai_integration_missing","ai_integration_ambiguous","ai_provider_unsupported","ai_credentials_unavailable","ai_credentials_invalid"]},"integrationProvider":{"type":"string"},"runtimeProvider":{"type":"string"},"model":{"type":"string","description":"Configured model id; contains no credential material"},"integrationId":{"type":"string","description":"Resolved integration id used to pin the subsequent credential fetch"}},"required":["enabled","targetAllowed","status"]}}},"paths":{"/sfp/api/integrations/ai/cherry-to-policy":{"get":{"operationId":"IntegrationsController_getCherryToPolicy","summary":"Resolve cherry-to target and AI availability policy","description":"Returns a non-secret, deterministic policy result for the cherry-to CLI. Credential material is never included; application callers retrieve the selected integration through the audited credentials endpoint.","parameters":[{"name":"project","required":true,"in":"query","description":"Registered repository identifier","schema":{"type":"string"}},{"name":"target","required":false,"in":"query","description":"Target branch to evaluate against cherryTo.targetBranches","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CherryToPolicyResponseDto"}}}},"403":{"description":"Forbidden - Requires role: owner, member, application"}},"tags":["Integrations"]}}}}
```

## Delete an integration

> Permanently delete an integration and its encrypted credentials.\
> \
> \*\*Authentication\*\*: Requires Owner role. This action cannot be undone.\
> \
> \*\*Effects:\*\*\
> \- Removes the integration configuration\
> \- Deletes encrypted credentials from secure storage\
> \- Removes integration reference from associated projects\
> \- Logs deletion in audit trail

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/integrations/{id}":{"delete":{"operationId":"IntegrationsController_remove","summary":"Delete an integration","description":"Permanently delete an integration and its encrypted credentials.\n\n**Authentication**: Requires Owner role. This action cannot be undone.\n\n**Effects:**\n- Removes the integration configuration\n- Deletes encrypted credentials from secure storage\n- Removes integration reference from associated projects\n- Logs deletion in audit trail","parameters":[{"name":"id","required":true,"in":"path","description":"Integration ID (UUID)","schema":{"type":"string"}}],"responses":{"204":{"description":"Integration deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Requires role: owner"},"404":{"description":"Integration not found"}},"tags":["Integrations"]}}}}
```

## Update an integration

> Update credentials, config, or default status of an existing integration. Only provided fields are updated — omitted fields remain unchanged.\
> \
> \*\*Authentication\*\*: Requires Owner role.\
> \
> \*\*Updatable fields:\*\*\
> \- \`credentials\`: New encrypted credentials (replaces existing)\
> \- \`config\`: Provider-specific configuration\
> \- \`isDefault\`: Toggle default status for this provider category\
> \
> \*\*Immutable fields\*\* (cannot be changed after creation):\
> \- \`provider\`\
> \- \`authType\`\
> \- \`projects\` / \`isGlobal\`

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"UpdateIntegrationDto":{"type":"object","properties":{"credentials":{"type":"object","description":"Updated credentials for the integration. Same format as create."},"config":{"type":"object","description":"Updated provider-specific configuration options"},"isDefault":{"type":"boolean","description":"Update default status for this provider category. AI providers are grouped — setting one AI provider as default unsets any other AI default."}}}}},"paths":{"/sfp/api/integrations/{id}":{"patch":{"operationId":"IntegrationsController_update","summary":"Update an integration","description":"Update credentials, config, or default status of an existing integration. Only provided fields are updated — omitted fields remain unchanged.\n\n**Authentication**: Requires Owner role.\n\n**Updatable fields:**\n- `credentials`: New encrypted credentials (replaces existing)\n- `config`: Provider-specific configuration\n- `isDefault`: Toggle default status for this provider category\n\n**Immutable fields** (cannot be changed after creation):\n- `provider`\n- `authType`\n- `projects` / `isGlobal`","parameters":[{"name":"id","required":true,"in":"path","description":"Integration ID (UUID)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIntegrationDto"}}}},"responses":{"200":{"description":"Integration updated successfully"},"400":{"description":"Invalid update (e.g., setting non-global integration as default)"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Requires role: owner"},"404":{"description":"Integration not found"}},"tags":["Integrations"]}}}}
```

## Resolve the ServiceNow release gate for a release request (internal)

> Internal worker-only endpoint: used by the request-release flow to decide whether a release must be gated by a ServiceNow change request, and to retrieve the connection + change-request text (including the candidate baseline changelog). Restricted to the internal worker (application token).

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"ResolveServiceNowGateDto":{"type":"object","properties":{"repositoryIdentifier":{"type":"string","description":"Repository identifier (owner/repo)"},"environments":{"description":"Target environment names for this release request","type":"array","items":{"type":"string"}},"releaseCandidate":{"type":"string","description":"Release candidate being released (domain:RC-NAME)"},"sourceReference":{"description":"GitHub/ADO issue that triggered the release request","allOf":[{"$ref":"#/components/schemas/ServiceNowSourceReferenceDto"}]}},"required":["repositoryIdentifier","environments","releaseCandidate"]},"ServiceNowSourceReferenceDto":{"type":"object","properties":{"type":{"type":"string","description":"Source tracker type","enum":["github","azure-devops"]},"repositoryIdentifier":{"type":"string","description":"GitHub repository identifier, when source is GitHub"},"issueNumber":{"type":"number","description":"GitHub issue number, when source is GitHub"},"organizationUrl":{"type":"string","description":"Azure DevOps organization URL, when source is Azure DevOps"},"project":{"type":"string","description":"Azure DevOps project, when source is Azure DevOps"},"workItemId":{"type":"number","description":"Azure DevOps work item id, when source is Azure DevOps"}},"required":["type"]}}},"paths":{"/sfp/api/integrations/servicenow/release-gate":{"post":{"operationId":"ServiceNowGateController_resolveReleaseGate","summary":"Resolve the ServiceNow release gate for a release request (internal)","description":"Internal worker-only endpoint: used by the request-release flow to decide whether a release must be gated by a ServiceNow change request, and to retrieve the connection + change-request text (including the candidate baseline changelog). Restricted to the internal worker (application token).","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveServiceNowGateDto"}}}},"responses":{"201":{"description":"Gate resolution returned"},"403":{"description":"Forbidden - Requires role: application"}},"tags":["Integrations"]}}}}
```

## Open or reuse a ServiceNow release change request (internal)

> Internal worker-only endpoint: resolves release-gate policy, opens/reuses the shared ServiceNow CR for the release candidate set, and registers the generic approval-gate record without returning ServiceNow credentials to the worker.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"OpenServiceNowReleaseGateDto":{"type":"object","properties":{"repositoryIdentifier":{"type":"string","description":"Repository identifier (owner/repo)"},"environments":{"description":"Target environment names for this release request","type":"array","items":{"type":"string"}},"releaseCandidate":{"type":"string","description":"Release candidate being released (domain:RC-NAME)"},"sourceReference":{"description":"GitHub/ADO issue that triggered the release request","allOf":[{"$ref":"#/components/schemas/ServiceNowSourceReferenceDto"}]},"requestedBy":{"type":"string","description":"Email of the human who requested the release"}},"required":["repositoryIdentifier","environments","releaseCandidate"]},"ServiceNowSourceReferenceDto":{"type":"object","properties":{"type":{"type":"string","description":"Source tracker type","enum":["github","azure-devops"]},"repositoryIdentifier":{"type":"string","description":"GitHub repository identifier, when source is GitHub"},"issueNumber":{"type":"number","description":"GitHub issue number, when source is GitHub"},"organizationUrl":{"type":"string","description":"Azure DevOps organization URL, when source is Azure DevOps"},"project":{"type":"string","description":"Azure DevOps project, when source is Azure DevOps"},"workItemId":{"type":"number","description":"Azure DevOps work item id, when source is Azure DevOps"}},"required":["type"]}}},"paths":{"/sfp/api/integrations/servicenow/release-gate/open":{"post":{"operationId":"ServiceNowGateController_openReleaseGate","summary":"Open or reuse a ServiceNow release change request (internal)","description":"Internal worker-only endpoint: resolves release-gate policy, opens/reuses the shared ServiceNow CR for the release candidate set, and registers the generic approval-gate record without returning ServiceNow credentials to the worker.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenServiceNowReleaseGateDto"}}}},"responses":{"201":{"description":"Change request opened or reused"},"403":{"description":"Forbidden - Requires role: application"}},"tags":["Integrations"]}}}}
```

## Read or refresh a ServiceNow release gate decision (internal)

> Internal worker-only endpoint: returns the cached ServiceNow gate decision and refreshes it from ServiceNow only when the per-gate cache is due.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"CheckServiceNowReleaseGateStatusDto":{"type":"object","properties":{"repositoryIdentifier":{"type":"string","description":"Repository identifier (owner/repo)"},"releaseCandidate":{"type":"string","description":"Release candidate being released (domain:RC-NAME)"},"environment":{"type":"string","description":"Target environment waiting on the ServiceNow gate"},"correlationId":{"type":"string","description":"Stable correlation id / approval gate id for this release CR"},"sysId":{"type":"string","description":"ServiceNow change request sys_id"},"changeNumber":{"type":"string","description":"ServiceNow change request number"},"requestedBy":{"type":"string","description":"Email of the human who requested the release (audit requestedBy)"},"changeUrl":{"type":"string","description":"Deep link to the change request in ServiceNow"},"sourceReference":{"description":"GitHub/ADO issue that triggered the release request","allOf":[{"$ref":"#/components/schemas/ServiceNowSourceReferenceDto"}]}},"required":["repositoryIdentifier","releaseCandidate","environment","correlationId"]},"ServiceNowSourceReferenceDto":{"type":"object","properties":{"type":{"type":"string","description":"Source tracker type","enum":["github","azure-devops"]},"repositoryIdentifier":{"type":"string","description":"GitHub repository identifier, when source is GitHub"},"issueNumber":{"type":"number","description":"GitHub issue number, when source is GitHub"},"organizationUrl":{"type":"string","description":"Azure DevOps organization URL, when source is Azure DevOps"},"project":{"type":"string","description":"Azure DevOps project, when source is Azure DevOps"},"workItemId":{"type":"number","description":"Azure DevOps work item id, when source is Azure DevOps"}},"required":["type"]}}},"paths":{"/sfp/api/integrations/servicenow/release-gate/status":{"post":{"operationId":"ServiceNowGateController_getReleaseGateStatus","summary":"Read or refresh a ServiceNow release gate decision (internal)","description":"Internal worker-only endpoint: returns the cached ServiceNow gate decision and refreshes it from ServiceNow only when the per-gate cache is due.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckServiceNowReleaseGateStatusDto"}}}},"responses":{"201":{"description":"Gate status returned"},"403":{"description":"Forbidden - Requires role: application"}},"tags":["Integrations"]}}}}
```

## Record a ServiceNow gate lifecycle event to the approval audit trail (internal)

> Internal worker-only endpoint: posted by the request-release worker when the change request is opened and when it is approved/rejected/timed out, so the gate appears in sfp\_approval\_audit. Does not create a pending approval. Restricted to the internal worker (application token).

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"RecordServiceNowGateEventDto":{"type":"object","properties":{"event":{"type":"string","description":"Gate lifecycle event","enum":["requested","approved","rejected","cancelled","timeout"]},"repositoryIdentifier":{"type":"string","description":"Repository identifier (owner/repo)"},"releaseCandidate":{"type":"string","description":"Release candidate being released (domain:RC-NAME)"},"environments":{"description":"Target environment names for this release request","type":"array","items":{"type":"string"}},"correlationId":{"type":"string","description":"Stable correlation id for this gate run (used as the audit entity id)"},"changeNumber":{"type":"string","description":"ServiceNow change request number"},"sysId":{"type":"string","description":"ServiceNow change request sys_id"},"requestedBy":{"type":"string","description":"Email of the human who requested the release (audit requestedBy)"},"changeUrl":{"type":"string","description":"Deep link to the change request in ServiceNow"},"sourceReference":{"description":"GitHub/ADO issue that triggered the release request","allOf":[{"$ref":"#/components/schemas/ServiceNowSourceReferenceDto"}]}},"required":["event","repositoryIdentifier","releaseCandidate","environments","correlationId"]},"ServiceNowSourceReferenceDto":{"type":"object","properties":{"type":{"type":"string","description":"Source tracker type","enum":["github","azure-devops"]},"repositoryIdentifier":{"type":"string","description":"GitHub repository identifier, when source is GitHub"},"issueNumber":{"type":"number","description":"GitHub issue number, when source is GitHub"},"organizationUrl":{"type":"string","description":"Azure DevOps organization URL, when source is Azure DevOps"},"project":{"type":"string","description":"Azure DevOps project, when source is Azure DevOps"},"workItemId":{"type":"number","description":"Azure DevOps work item id, when source is Azure DevOps"}},"required":["type"]}}},"paths":{"/sfp/api/integrations/servicenow/release-gate/event":{"post":{"operationId":"ServiceNowGateController_recordReleaseGateEvent","summary":"Record a ServiceNow gate lifecycle event to the approval audit trail (internal)","description":"Internal worker-only endpoint: posted by the request-release worker when the change request is opened and when it is approved/rejected/timed out, so the gate appears in sfp_approval_audit. Does not create a pending approval. Restricted to the internal worker (application token).","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordServiceNowGateEventDto"}}}},"responses":{"201":{"description":"Event recorded"},"403":{"description":"Forbidden - Requires role: application"}},"tags":["Integrations"]}}}}
```

## Check health of platform integrations for registered projects

> Verifies that the source control platform (GitHub or Azure DevOps) is reachable and that credentials are valid for each registered project.\
> \
> \## How it works\
> \
> Each project registered via \`POST /projects\` declares a \`platform\` field (\`github\` or \`azure-devops\`). This endpoint resolves the credentials for each project's platform and makes a lightweight API call to confirm access.\
> \
> \### Credential resolution\
> \
> \| Platform | What is checked |\
> \|----------|----------------|\
> \| \*\*GitHub\*\* | Uses the GitHub App credentials (user-configured integration first, falls back to built-in App from server environment). Calls \`GET /repos/{owner}/{repo}\` to confirm repository access. |\
> \| \*\*Azure DevOps\*\* | Uses the Service Principal credentials from the configured integration. Calls \`GET /\_apis/connectiondata\` to confirm API connectivity. |\
> \
> \### Modes\
> \
> \| Parameter | Behavior |\
> \|-----------|----------|\
> \| No \`project\` | Lists \*\*all\*\* registered projects and checks each one. Useful for a full integration health overview. |\
> \| \`project=flxbl-io/sf-core\` | Checks \*\*only\*\* the specified project. Useful for verifying a single onboarding. |\
> \
> \### Response statuses\
> \
> \| Overall status | Meaning |\
> \|---------------|---------|\
> \| \`healthy\` | All projects have working platform integrations |\
> \| \`degraded\` | Some projects are healthy, others are not |\
> \| \`unhealthy\` | No project has a working platform integration |\
> \
> \### Common failure causes\
> \
> \- \*\*GitHub\*\*: App not installed on the organization, or repository is private and not accessible to the App\
> \- \*\*Azure DevOps\*\*: Service Principal not registered via \`POST /integrations\`, invalid client credentials, or organization URL is wrong\
> \
> \### Authentication\
> Requires any authenticated role (Owner, Member, or Application token).

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"PlatformHealthResultDto":{"type":"object","properties":{"status":{"type":"string","description":"Overall health across all checked projects:\n- `healthy` — every project's platform integration is reachable\n- `degraded` — at least one project is healthy but others are unhealthy or not configured\n- `unhealthy` — no project has a healthy platform integration","enum":["healthy","degraded","unhealthy"]},"timestamp":{"type":"string","description":"ISO 8601 timestamp of when the health check was performed"},"platforms":{"description":"Per-project health check results. One entry per registered project with a supported platform (GitHub or Azure DevOps).","type":"array","items":{"$ref":"#/components/schemas/PlatformComponentHealthDto"}}},"required":["status","timestamp","platforms"]},"PlatformComponentHealthDto":{"type":"object","properties":{"provider":{"type":"string","description":"Source control platform for this project","enum":["github","azure-devops","none"]},"project":{"type":"string","description":"Project identifier that was checked"},"status":{"type":"string","description":"Health status of the platform integration for this project:\n- `healthy` — credentials are valid and the platform API confirmed access to the repository\n- `unhealthy` — credentials are missing, invalid, expired, or the platform API is unreachable\n- `not_configured` — no integration or project is registered for the requested platform\n- `initializing` — server recently started; token cache is still warming up (transient, resolves within ~60s)","enum":["healthy","unhealthy","not_configured","initializing"]},"message":{"type":"string","description":"Human-readable explanation of the health check result"},"latency":{"type":"number","description":"Round-trip time in milliseconds for the health check API call"}},"required":["provider","project","status","message"]}}},"paths":{"/sfp/api/integrations/platforms/health":{"get":{"operationId":"PlatformHealthController_checkHealth","summary":"Check health of platform integrations for registered projects","description":"Verifies that the source control platform (GitHub or Azure DevOps) is reachable and that credentials are valid for each registered project.\n\n## How it works\n\nEach project registered via `POST /projects` declares a `platform` field (`github` or `azure-devops`). This endpoint resolves the credentials for each project's platform and makes a lightweight API call to confirm access.\n\n### Credential resolution\n\n| Platform | What is checked |\n|----------|----------------|\n| **GitHub** | Uses the GitHub App credentials (user-configured integration first, falls back to built-in App from server environment). Calls `GET /repos/{owner}/{repo}` to confirm repository access. |\n| **Azure DevOps** | Uses the Service Principal credentials from the configured integration. Calls `GET /_apis/connectiondata` to confirm API connectivity. |\n\n### Modes\n\n| Parameter | Behavior |\n|-----------|----------|\n| No `project` | Lists **all** registered projects and checks each one. Useful for a full integration health overview. |\n| `project=flxbl-io/sf-core` | Checks **only** the specified project. Useful for verifying a single onboarding. |\n\n### Response statuses\n\n| Overall status | Meaning |\n|---------------|---------|\n| `healthy` | All projects have working platform integrations |\n| `degraded` | Some projects are healthy, others are not |\n| `unhealthy` | No project has a working platform integration |\n\n### Common failure causes\n\n- **GitHub**: App not installed on the organization, or repository is private and not accessible to the App\n- **Azure DevOps**: Service Principal not registered via `POST /integrations`, invalid client credentials, or organization URL is wrong\n\n### Authentication\nRequires any authenticated role (Owner, Member, or Application token).","parameters":[{"name":"project","required":false,"in":"query","description":"Project identifier to check (e.g., `flxbl-io/sf-core` for GitHub, `org/project/repo` for Azure DevOps). Omit to check all registered projects.","schema":{"type":"string"}}],"responses":{"200":{"description":"Platform health check results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformHealthResultDto"}}}},"401":{"description":"Unauthorized — missing or invalid bearer token"},"403":{"description":"Forbidden - Requires role: owner, member, application"},"404":{"description":"Project not found — the specified project identifier does not exist"}},"tags":["Integrations"]}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.flxbl.io/flxbl/sfp-server/api-reference/integrations.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
