---
title: "Connect a third-party signal source (organization admin only)"
method: POST
path: "/api/v1/organizations/{organization_id}/signal_integrations"
tags: ["organizations"]
---

# Connect a third-party signal source (organization admin only)

`POST /api/v1/organizations/{organization_id}/signal_integrations`

## Request

- Base URL: `https://composal.com` (the document declares no server; this is the origin it was published from)
- URL: `https://composal.com/api/v1/organizations/{organization_id}/signal_integrations`
- Auth: HTTP bearer

Creates the integration and stores the supplied credentials as organization-scoped secrets. The response carries the `inbound_url` to paste into the provider's webhook configuration.

## Path parameters

- `organization_id` string, required

## Request body

- SignalIntegrationCreatePayload
  - `provider` 'sentry' | 'planetscale', required
  - `mode` 'connected' | 'managed': `connected` is a customer-owned credential pasted into Vex; `managed` is a Vex-provisioned resource where Vex already holds the credential.
  - `name` string, required
  - `webhook_secret` string: The provider's signing secret. Stored as an organization secret; never read back.
  - `api_token` string: Optional provider API token for target discovery and backfill.
  - `config` object

## Response `200`

The signal integration

- object
  - `signal_integration` SignalIntegration, required: One organization's connection to a signal source. Secret values are never rendered; `webhook_secret_stored` / `api_token_stored` say only whether one exists.
    - `id` string, required: Public id (`sint_…`).
    - `organization_id` string, required
    - `provider` 'sentry' | 'planetscale', required
    - `mode` 'connected' | 'managed', required: `connected` is a customer-owned credential pasted into Vex; `managed` is a Vex-provisioned resource where Vex already holds the credential.
    - `name` string, required
    - `status` 'pending' | 'active' | 'failed' | 'disabled', required
    - `inbound_url` string, required: The absolute URL to paste into the provider's webhook configuration.
    - `inbound_path` string, required
    - `webhook_secret_stored` boolean, required
    - `api_token_stored` boolean, required
    - `config` object, required
    - `unmapped_delivery_count` integer, required: Deliveries accepted whose provider resource matched no enabled target.
    - `rejected_signature_count` integer, required: Deliveries rejected for a bad or missing signature.
    - `failure_message` string, nullable, required
    - `target_count` integer, required
    - `last_received_at` string, nullable
    - `last_verified_at` string, nullable
    - `created_at` string, nullable
    - `updated_at` string, nullable

## Other responses

- `201`: The signal integration
- `401`: Unauthorized
- `403`: The caller is not an administrator of the organization
- `404`: Not found
- `422`: The request failed validation
- `502`: Bad gateway

---

[API](https://skmtc.dev/composal/apis/vex-api.md) - [All operations](https://skmtc.dev/composal/apis/vex-api/llms.txt) - [OpenAPI document](https://skmtc.dev/composal/apis/vex-api/revisions/74298a24e040?raw)
