Skip to main content
POST
/
api
/
partner
/
v1
/
webhook-endpoints
curl -sS -X POST https://app.opentrain.ai/api/partner/v1/webhook-endpoints \
  -H "Authorization: Bearer $OT_PARTNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-platform.example.com/webhooks/opentrain",
    "eventTypes": ["contract.started", "contract.ended", "install.revoked"]
  }'
{
  "webhookEndpoint": {
    "id": "<ENDPOINT_ID>",
    "url": "https://your-platform.example.com/webhooks/opentrain",
    "eventTypes": ["contract.started", "contract.ended", "install.revoked"],
    "status": "ACTIVE",
    "createdAt": "2026-06-12T10:00:00.000Z",
    "consecutiveFailures": 0,
    "disabledAt": null,
    "disabledReason": null
  },
  "secret": "whsec_<SECRET>",
  "message": "Store the secret now — it is only returned once. Use it to verify the X-OpenTrain-Signature header on deliveries."
}
Registers a webhook endpoint to receive lifecycle events. The response includes the HMAC signing secret once — store it immediately; no later call returns it. If you lose it, delete the endpoint and create a new one. Delivery starts with events created after the endpoint is registered — there is no backfill of earlier events. Link projects and subscribe before contracts you care about begin. Requirements: webhooks:manage scope.

Request

url
string
required
Delivery URL. Must be HTTPS (http is allowed for localhost only). Redirects are not followed.
eventTypes
string[]
required
At least one of: contract.started, contract.ended, project_link.created, project_link.removed, install.revoked, milestone.funded, milestone.budget_low, milestone.budget_depleted.

Response

webhookEndpoint
object
The created endpoint: {id, url, eventTypes, status, createdAt, consecutiveFailures, disabledAt, disabledReason} — same shape as GET /webhook-endpoints/{endpointId}.
secret
string
HMAC-SHA256 signing secret for verifying deliveries. Shown only in this response.
message
string
Reminder that the secret will not be shown again.

Errors

StatuscodeMeaning
400BAD_REQUESTBody not valid JSON, url missing/not HTTPS, or eventTypes empty/contains an unknown type
401UNAUTHORIZEDMissing, invalid, or revoked token
403FORBIDDENToken lacks webhooks:manage
409CONFLICTEndpoint limit reached for this install
curl -sS -X POST https://app.opentrain.ai/api/partner/v1/webhook-endpoints \
  -H "Authorization: Bearer $OT_PARTNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-platform.example.com/webhooks/opentrain",
    "eventTypes": ["contract.started", "contract.ended", "install.revoked"]
  }'
{
  "webhookEndpoint": {
    "id": "<ENDPOINT_ID>",
    "url": "https://your-platform.example.com/webhooks/opentrain",
    "eventTypes": ["contract.started", "contract.ended", "install.revoked"],
    "status": "ACTIVE",
    "createdAt": "2026-06-12T10:00:00.000Z",
    "consecutiveFailures": 0,
    "disabledAt": null,
    "disabledReason": null
  },
  "secret": "whsec_<SECRET>",
  "message": "Store the secret now — it is only returned once. Use it to verify the X-OpenTrain-Signature header on deliveries."
}