---
title: "Deliver a webhook event to a partner URL"
method: POST
path: "/webhooks/cloud-deliver"
tags: ["Webhooks"]
---

# Deliver a webhook event to a partner URL

`POST /webhooks/cloud-deliver`

What it does: Executes an outbound HTTP POST to the partner URL in the request body, delivering a webhook event payload on behalf of the credentialing platform. The service sets an Idempotency-Key header (SHA-256 over messageId, webhookId, and eventType) on the outbound request and, when OAuth is configured, mints an Authorization: Bearer token before dispatching.

When to use: This endpoint is an internal callback invoked by the Cloud Tasks delivery queue; it is not intended to be called directly by external API consumers.

How (preconditions and authentication): The request must include the X-Credentialing-Api-Key header with a valid key; an absent or invalid key returns 401. The body must be a JSON object containing at minimum webhookUrl (the partner's receiving endpoint) and eventType. Optional body fields include webhookId, messageId, headers (additional outbound headers), eventPayload (the event body sent to the partner), and oauthConfiguration (when absent or blank, the service falls back to static-header authentication mode). The tenant-id and user-id headers are forwarded as delivery context. A 400 is returned when the body is null or when webhookUrl or eventType is missing or blank; supply all required fields to resolve.

What you get back: On success (200) the partner endpoint returned a 2xx response and the body is {"message": "Webhook delivered successfully"}. The service performs internal exponential-backoff retries (configurable maximum) before giving up; if all retries are exhausted it returns 502 with a body of the form {"message": ..., "statusCode": ..., "error": ...}. When the dead-letter queue is enabled, an exhausted event is instead published to the DLQ and acknowledged with a 200 {"message": ..., "dlq": true} body so it can be replayed later.

## Headers

- `X-CloudTasks-TaskRetryCount` string
- `tenant-id` string
- `user-id` string

## Request body

- object — Free-form Cloud Tasks delivery payload; see field descriptions above.

## Response `200`

The partner endpoint acknowledged the event with a 2xx response, or the exhausted event was published to the dead-letter queue for later replay.

## Other responses

- `400` — Two distinct 400 shapes are possible. (1) The task payload was well-formed JSON but missing or malformed: the body was null, or webhookUrl or eventType was absent or blank; resend the task with both required fields populated. This returns the flat {"message": ...} body shown in the missingRequiredFields example. (2) The request body was not valid JSON: this is caught by the framework before the handler runs and returns the structured ApiError shape shown in the malformedJson example instead.
- `401` — The X-Credentialing-Api-Key header was missing or did not match the configured key. Supply the correct credentialing API key and retry.
- `502` — The partner endpoint returned a non-2xx response or was unreachable for this delivery attempt. This is returned both on non-final attempts (Cloud Tasks will retry) and on the final attempt when the event could not be published to the DLQ (e.g. the DLQ is disabled, or publishing itself failed). Inspect statusCode and error, verify the partner endpoint, then allow Cloud Tasks to retry.

---

[API](https://skmtc.net/certifyos/apis/certify-api-layer.md) · [All operations](https://skmtc.net/certifyos/apis/certify-api-layer/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/certifyos/certify-api-layer/revisions/563848e0ecc0/schema)
