---
title: "Generate a connection's signing secret"
method: POST
path: "/api/v1/connections/{connection_id}/trigger-ingress/signing-secret/generate"
tags: ["Triggers"]
---

# Generate a connection's signing secret

`POST /api/v1/connections/{connection_id}/trigger-ingress/signing-secret/generate`

## Request

- Base URL: `https://$SCALEKIT_ENVIRONMENT_URL`
- URL: `https://$SCALEKIT_ENVIRONMENT_URL/api/v1/connections/{connection_id}/trigger-ingress/signing-secret/generate`
- Auth: OAuth 2
  - Client credentials
  - Token URL: `https://$SCALEKIT_ENVIRONMENT_URL/oauth/token`
- TypeScript: <https://skmtc.dev/scalekit/apis/scalekit-api-reference/docs/api/v1/connections/:connection_id/trigger-ingress/signing-secret/generate/post.ts> (a function with typed inputs; its response is checked against the schema)

Generates a random signing secret for a connection's webhook URL, stores it, and returns it in plain text together with the URL that carries it. Use this endpoint for a provider that sends no signature of its own (provides_bearer_secret is true on its triggers), after CreateTriggerIngressEndpoint. Pass the connection ID in the path; the body is empty. The provider presents the secret back on every event, in an `Authorization: Bearer <secret>` header, the `X-Scalekit-Webhook-Secret` header, or the final path segment of url_with_secret, and an event without it is rejected. The first call on an endpoint with no secret sets one. A call where a secret already exists starts a rotation rather than replacing it, exactly as SetTriggerSigningSecret does: both secrets are accepted until you confirm the rotation with ConfirmTriggerSigningSecretRotation, or for at most 24 hours. A provider that signs its own events takes its secret from its app configuration through SetTriggerSigningSecret instead, and is refused here. Returns the secret in plain text, url_with_secret, and the endpoint with its masked secret and rotation state. The plain-text secret appears only in this response and is never returned again; generate another if it is lost.

## Path parameters

- `connection_id` string, required

## Request body

- TriggerServiceGenerateTriggerSigningSecretBody

## Response `200`

The generated secret in plain text, the webhook URL with the secret appended, and the endpoint's state, including whether a rotation is now in progress

- TriggersGenerateTriggerSigningSecretResponse: The one response in this API that carries a signing secret in plain text, and the only time you ever see it: endpoint shows the secret masked, as every other webhook URL response does, and the plain text appears only in signing_secret and url_with_secret.
  - `endpoint` TriggersTriggerIngressEndpoint: The webhook URL a provider sends a connection's events to, and the state of the secret those events are signed with. This message never carries the signing secret itself: masked_signing_secret shows at most its last four characters, so you can tell which secret is stored. The only response that returns a secret in plaintext is GenerateTriggerSigningSecret's, once, for a secret Scalekit generates.
    - `connection_id` string: ID of the connection this webhook URL belongs to.
    - `id` string: Unique identifier of the connection's webhook endpoint.
    - `masked_signing_secret` string: The stored secret with all but its last four characters replaced, or every character replaced for a secret of 8 characters or fewer. Present only when one is configured. Enough to compare against the secret the provider's app configuration shows, and never enough to sign with.
    - `previous_signing_secret_expires_at` string, date-time: When the previous secret stops being accepted even if the rotation is never confirmed: 24 hours after the rotation started. Absent when no rotation is in progress.
    - `rotation_in_progress` boolean: Whether the previous signing secret is still accepted alongside the current one. True from the moment a different secret replaces a stored one until the rotation is confirmed, or until previous_signing_secret_expires_at passes.
    - `signing_secret_configured` boolean: Whether a signing secret is stored. While false, every event sent to the URL is answered with 503 so the provider retries it, and the provider's own URL verification fails.
    - `signing_secret_rotation_id` string, int64: Identifies the latest signing-secret rotation; it increases by one each time a rotation starts. Zero when none has ever started. Pass this value to ConfirmTriggerSigningSecretRotation to confirm this specific rotation. A value naming a rotation that a newer one has since replaced is refused rather than confirming the wrong rotation.
    - `url` string: The URL to paste into the provider's app configuration as the event destination. It is built on your environment's domain, using its custom domain when one is set, and ends in a random token unique to this connection, so treat it as confidential. Returned whether or not a signing secret has been set. The URL accepts request bodies up to 1 MB and answers a larger one with 413. Until a signing secret is set it answers events with 503, so the provider retries them; an event that fails signature verification is answered with 400.
  - `signing_secret` string: The generated secret, in plain text. Returned only in this response and never again by any endpoint, nor written to a log. The provider presents it back on every event in exactly one of three ways: an `Authorization: Bearer <secret>` header, the `X-Scalekit-Webhook-Secret` header, or the final path segment of url_with_secret.
  - `url_with_secret` string: endpoint.url with the secret appended as a final path segment. Paste this into the provider's console when the provider cannot send a custom header. It is as sensitive as signing_secret and is likewise returned only in this response.

## Other responses

- `400`: Invalid request, nothing written - connection_id is not a valid connection ID; the connection's provider signs its own events, so its secret is copied from the provider's app configuration and stored with SetTriggerSigningSecret instead (error_code TRIGGER_SIGNING_SECRET_NOT_GENERATABLE); or the provider's webhook trigger definitions are temporarily unavailable (error_code TRIGGER_INGRESS_DEFINITIONS_UNAVAILABLE)
- `404`: Not found - no webhook URL has been created for this connection yet (error_code TRIGGER_INGRESS_ENDPOINT_NOT_CREATED; call CreateTriggerIngressEndpoint first), the connection does not exist in this environment (error_code RESOURCE_NOT_FOUND), or Triggers is not enabled for the environment (error_code RESOURCE_NOT_FOUND)
- `409`: Conflict - a rotation is already in progress. Confirm it with ConfirmTriggerSigningSecretRotation, or wait for the previous secret's expiry, before generating another secret
- `500`: Internal error - the secret could not be generated or stored, or the endpoint could not be read back; retry the request

## Changes

- **2026-10-30** `f47f1022d844`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/scalekit/apis/scalekit-api-reference/changes/api/v1/connections/:connection_id/trigger-ingress/signing-secret/generate/post.md)

---

[API](https://skmtc.dev/scalekit/apis/scalekit-api-reference.md) - [All operations](https://skmtc.dev/scalekit/apis/scalekit-api-reference/llms.txt) - [OpenAPI document](https://skmtc.dev/scalekit/apis/scalekit-api-reference/revisions/f47f1022d844?raw)
