> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.jelliu.co/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.jelliu.co/_mcp/server.

# Retry a delivery

POST https://api.jelliu.co/api/webhooks/deliveries/{deliveryId}/retry

Queues the delivery for an immediate attempt, regardless of its state (`failed`, `canceled`,
`succeeded` or `pending`), except while an attempt is in flight (`delivering`), which returns
`409`. The attempt counter continues from its current value, the same event (same `webhook-id`) is
sent to the endpoint's current URL with its current secret, and the delivery is marked
`manual: true`, so it does not affect endpoint health. A delivery that has used all 12 attempts
receives one additional attempt, with no further automatic retries if it fails. If the endpoint is
disabled when the attempt runs, the delivery is canceled (`endpoint_disabled`).

**Side effects.** Sets the delivery back to `pending`, due immediately; the dispatcher sends it within seconds.

**Idempotency.** Repeating the call while the first retry is still pending leaves a single pending
attempt. Once that attempt has run, a new call queues another.

**Access**
- **Required scope:** `full`. Human users need the owner or admin role.
- **Rate limit:** General API (120–600 requests/min per workspace, by plan) plus the configuration-mutations limit — 10 requests/min per workspace, shared with other configuration changes. See [Rate limits](/rate-limits).
- **Plan:** Requires an active subscription (`active`, `trialing` or `past_due`); without one the request is refused with `403 BILLING_ERROR` (`metadata.kind: subscription_required`). See [Billing and usage](/platform/billing-and-usage#without-an-active-subscription).


Reference: https://developer.jelliu.co/api-reference/webhooks/post-webhooks-deliveries-by-delivery-id-retry

## Authentication

- `Authorization` header (bearer token, required) — Workspace API key: `jl_` followed by 64 lowercase hex characters, created by the workspace owner in the dashboard (**Settings → API Keys**) and sent as `Authorization: Bearer jl_...`. The plaintext is shown once, at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys. | Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes | | --- | --- | --- | --- | | `read` | Yes | No | No | | `write` | Yes | Yes | No | | `full` | Yes | Yes | Yes | Operations restricted to admins or owners reject keys without the `full` scope with `403`, and say so in their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret — that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds. See [Authentication](/authentication).

## Request

### Path parameters

- `deliveryId` (string, required) — Id of a webhook delivery (`dlv_` plus 26 characters), as returned in `id` by `GET /api/webhooks/{webhookId}/deliveries` and sent in the `x-jelliu-delivery-id` header. A delivery of another workspace, an unknown id or a value that is not a delivery id answers `404`.

## Response

### 202

Queued.

- `data` (ApiWebhooksDeliveriesDeliveryIdRetryPostResponsesContentApplicationJsonSchemaData, required)

## Errors

### 401 Unauthorized Error

No usable credential. Either the `Authorization` header is missing or is not a well-formed `Bearer jl_…` key, or the key is unknown, revoked or expired. Do not retry with the same key. See [Authentication](/authentication#401-unauthorized).

- `error` (ErrorResponseError, required) — The error object. Always has `code` and `message`.

### 403 Forbidden Error

Role below admin, an API key without the `full` scope, or a suspended workspace. Without an active subscription the request is refused with `BILLING_ERROR` and `metadata.kind` = `subscription_required`.

- `error` (ErrorResponseError, required) — The error object. Always has `code` and `message`.

### 404 Not Found Error

No delivery with this id in the workspace, its webhook was deleted, or `deliveryId` is not a delivery id.

- `error` (ErrorResponseError, required) — The error object. Always has `code` and `message`.

### 409 Conflict Error

An attempt of this delivery is in flight. Wait for it to finish.

- `error` (ErrorResponseError, required) — The error object. Always has `code` and `message`.

### 429 Too Many Requests Error

The configuration-mutations limit (10/min) or the general API limit was exceeded.

- `error` (ErrorResponseError, required) — The error object. Always has `code` and `message`.

## Types

### ApiWebhooksDeliveriesDeliveryIdRetryPostResponsesContentApplicationJsonSchemaData

- `delivery_id` (string, required)
- `status` (enum, required)
  - Allowed values: `pending`

### ErrorResponseError

The error object. Always has `code` and `message`.

- `code` (string, required) — Stable machine-readable error code (for example `VALIDATION_FAILED`, `PAYLOAD_TOO_LARGE`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `BILLING_ERROR`, `COMPLIANCE_BLOCKED`, `RATE_LIMIT_EXCEEDED`, `INTERNAL_ERROR`). Switch on this, not on `message`. See [Errors](/errors).
- `message` (string, required) — Human-readable explanation. English or Spanish depending on the route; may change without notice.
- `details` (ErrorResponseErrorDetails, optional) — Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields); * for a rejected multipart upload (file in an unexpected field, too many files), a list with the upload error `code` (for example `LIMIT_UNEXPECTED_FILE`) and the `field` name. Absent when the value was rejected outside the route's own validation: a malformed id, number or date the database could not read, or a JSON body that does not parse.
- `metadata` (map from string to any, optional) — Structured detail exposed for a small allowlist of codes only — for example `BILLING_ERROR` carries `limit`, `current` and `tier` (resource caps), `tier` alone (feature gates), or `tier` = `none` with `kind` = `subscription_required` when the workspace has no active subscription. See [Errors](/errors).

### ErrorResponseErrorDetails

Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields); * for a rejected multipart upload (file in an unexpected field, too many files), a list with the upload error `code` (for example `LIMIT_UNEXPECTED_FILE`) and the `field` name. Absent when the value was rejected outside the route's own validation: a malformed id, number or date the database could not read, or a JSON body that does not parse.

- Field map: Field map
- Issue list: list of ErrorResponseErrorDetailsOneOf1Items

### Field map

- `formErrors` (list of string, optional)
- `fieldErrors` (map from string to list of string, optional)

### ErrorResponseErrorDetailsOneOf1Items

- `path` (ErrorResponseErrorDetailsOneOf1ItemsPath, optional) — Dot-separated string, or an array of keys.
- `message` (string, optional)
- `code` (string, optional) — Zod issue code, for example `invalid_type`.

### ErrorResponseErrorDetailsOneOf1ItemsPath

Dot-separated string, or an array of keys.

- string
- list of ErrorResponseErrorDetailsOneOf1ItemsPathOneOf1Items

### ErrorResponseErrorDetailsOneOf1ItemsPathOneOf1Items

- string
- integer

## Examples

**Response**

```json
{
  "data": {
    "delivery_id": "dlv_01K6B2W7M4P1R8T5V2X9Z6B3D0",
    "status": "pending"
  }
}
```

**SDK Code**

```python Webhooks_postWebhooksDeliveriesByDeliveryIdRetry_example
import requests

url = "https://api.jelliu.co/api/webhooks/deliveries/dlv_01K6B3X0R2A5C8E1G4J7K0M3N6/retry"

headers = {"Authorization": "Bearer <token>"}

response = requests.post(url, headers=headers)

print(response.json())
```

```javascript Webhooks_postWebhooksDeliveriesByDeliveryIdRetry_example
const url = 'https://api.jelliu.co/api/webhooks/deliveries/dlv_01K6B3X0R2A5C8E1G4J7K0M3N6/retry';
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Webhooks_postWebhooksDeliveriesByDeliveryIdRetry_example
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.jelliu.co/api/webhooks/deliveries/dlv_01K6B3X0R2A5C8E1G4J7K0M3N6/retry"

	req, _ := http.NewRequest("POST", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Webhooks_postWebhooksDeliveriesByDeliveryIdRetry_example
require 'uri'
require 'net/http'

url = URI("https://api.jelliu.co/api/webhooks/deliveries/dlv_01K6B3X0R2A5C8E1G4J7K0M3N6/retry")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java Webhooks_postWebhooksDeliveriesByDeliveryIdRetry_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.jelliu.co/api/webhooks/deliveries/dlv_01K6B3X0R2A5C8E1G4J7K0M3N6/retry")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php Webhooks_postWebhooksDeliveriesByDeliveryIdRetry_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.jelliu.co/api/webhooks/deliveries/dlv_01K6B3X0R2A5C8E1G4J7K0M3N6/retry', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp Webhooks_postWebhooksDeliveriesByDeliveryIdRetry_example
using RestSharp;

var client = new RestClient("https://api.jelliu.co/api/webhooks/deliveries/dlv_01K6B3X0R2A5C8E1G4J7K0M3N6/retry");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift Webhooks_postWebhooksDeliveriesByDeliveryIdRetry_example
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.jelliu.co/api/webhooks/deliveries/dlv_01K6B3X0R2A5C8E1G4J7K0M3N6/retry")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```