---
title: "Prepare a staged builder webhook signing secret"
method: POST
path: "/api/v1/webhooks/{id}/rotate-secret/prepare"
tags: ["Webhooks"]
---

# Prepare a staged builder webhook signing secret

`POST /api/v1/webhooks/{id}/rotate-secret/prepare`

Creates a pending signing secret while the current secret remains active. Deploy the returned one-time signing_secret to the receiver before calling activate. The response exposes secret_rotation.status=pending; an existing pending secret is returned again so a lost response can be recovered safely.

## Path parameters

- `id` integer, required

## Headers

- `Idempotency-Key` string

## Response `200`

Webhook destination with the prepared signing secret

- object
  - `object` 'webhook', required
  - `data` WebhookEndpoint, required
    - `id` integer, required
    - `object` 'webhook', required
    - `name` string, required
    - `url` string, uri, required
    - `event_types` WebhookEventType[], required
    - `trade_filters` LargeTradeSubscriptionFilters, required — All present fields narrow large_trade_inserted_v2 delivery. Grade is observed at publication; ungraded trades do not match min_grade. An empty object matches every large trade.
      - `condition_id` string — Raw provider condition ID or mkt_-prefixed market ID.
      - `wallet` string — Polymarket wallet address; matching is case-insensitive.
      - `min_grade` 'S' | 'A' | 'B' | 'C' | 'D' | 'F' — S is best; ungraded trades do not match.
      - `min_size_usd` string — Positive USD notional as an exact decimal string.
    - `status` 'pending_verification' | 'active' | 'disabled', required
    - `verified_at` string, date-time, nullable, required
    - `verification_token_expires_at` string, date-time, required
    - `failure_count` integer, required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `retry_policy` WebhookRetryPolicy, required
      - `max_attempts` 8, required
      - `terminal_status` 'dead_letter', required
      - `retry_horizon_seconds` 7380, required — Total wait from a delivery's first failed attempt to its last retry: 60, 120, 240, 480, 960, 1920 and 3600 seconds. A delivery still failing after that is dead_letter.
      - `disable_after_consecutive_failures` 8, required — Consecutive failed attempts, across all of this endpoint's deliveries, after which the endpoint is disabled and its queued deliveries are dead-lettered. Any successful attempt resets the count.
    - `secret_rotation` WebhookSecretRotation, required
      - `status` 'idle' | 'pending' | 'overlap', required — idle when no staged rotation exists, pending after prepare, and overlap after activate while both signing secrets are accepted.
      - `overlap_expires_at` string, date-time, nullable, required — When the previous signing secret stops being emitted and accepted. null outside the overlap phase.
    - `signing_secret` string — Returned only on create, immediate rotate-secret, staged rotate-secret/prepare, or staged rotate-secret/activate. Never returned by list, get, update, delete, verify, or retire.
    - `verification` WebhookVerification
      - `token` string, required — One-time verification token returned only on create or URL change. Pass it to POST /api/v1/webhooks/{id}/verify, which activates the endpoint only when the destination also answers the signed webhook.verification challenge with a 2xx.
      - `expires_at` string, date-time, required
  - `meta` ResponseMeta, required
    - `request_id` string, required — Unique request ID (req_ prefix). The same value as the X-Request-Id response header, the request's usage accounting row and its log lines.
    - `cached` boolean, required
    - `cache_age_s` integer — Cache age in seconds. Omitted when the response was not cached, and also when it was cached but its age cannot be established (an entry stored before its cache carried a computed instant). Never a placeholder: an unknown age is reported as no value rather than as the cache TTL.
    - `cost` integer, required — Advisory request weight (relative compute cost). 1 for simple reads; higher for heavier endpoints. Not a credit/price.
    - `ranking_generation` integer — Committed PostgreSQL-owned leaderboard generation for the returned rows and cursor. Present on GET /api/v1/leaderboard; omitted on endpoints that do not read this ranking.
    - `ranking_as_of` string, date-time — Authoritative RFC3339 timestamp from cache_generations.updated_at for ranking_generation. It is read in the same repeatable-read snapshot as the leaderboard rows and is not request time, cache write time, or row insertion order.
    - `directional_source` 'live' | 'degraded' — Which path produced the team-directional read on this response. Only present on endpoints that compute one (today: GET /api/v1/sports-edge-signals). "live" means the read RAN. "degraded" means it FAILED, so nothing was measured and the ranking fell back to raw conviction. The flag describes the READ, not its consequence: a read that ran and found nothing groupable also leaves the directional fields null, and that is honestly "live" -- the per-signal nulls already say "nothing to enrich here", so this snapshot-level flag carries only what they cannot, namely whether the read ran at all. A degraded response is cached on the shorter degraded TTL so it self-heals. Reported SEPARATELY from ranking_source because the two degradations are independent -- a sharp-money DB miss weakens the ranking DATA, a directional failure removes a ranking WEIGHT -- and a consumer down-weighting a degraded response needs to know which input it lost. Omitted on endpoints that compute no directional read.
    - `ranking_source` 'live' | 'db_only' — Which ranking-data path produced this response. Only present on endpoints that can degrade a ranking (today: GET /api/v1/sports-edge-signals). "live" is the normal path (the current holder pile from the provider batch); "db_only" is the degraded fallback (a truthful but weaker trader_markets ranking) served when the live sharp-money ranking batch is unavailable (a sharp-money DB read failure, not a Polymarket outage) and cached on a shorter TTL, so a consumer can down-weight or skip it. Omitted on endpoints that never degrade.
    - `category_skill_source` 'live' | 'partial' | 'degraded' | 'unavailable' — Whole filtered snapshot category-evidence status before pagination. Operational live always remains partial source coverage.
    - `category_skill_model_version` string
    - `category_skill_taxonomy_version` string
    - `category_skill_platform` 'polymarket'
    - `category_skill_scope` 'observed_goldsky_primary_taker_fill'
    - `category_skill_source_coverage` 'partial_whale_threshold_fills' | 'graded_wallet_fills'
    - `category_skill_observation_started_at` string, date-time
    - `category_skill_model_operationally_degraded` boolean — Whole-model operational readiness captured with the category model snapshot. Present on category-enriched responses even when the filtered signal list is empty. When true, category_skill_source is degraded and sports-edge-signals uses the shorter degraded cache TTL.
    - `category_skill_status_counts` object
      - `live` integer, required
      - `insufficient` integer, required
      - `stale` integer, required
      - `unknown` integer, required
      - `degraded` integer, required
    - `category_skill_base_payload_hash` string — SHA-256 of the funded signal membership/order/rank/cursor vector immediately before category-skill enrichment. Sports-edge-signals only.
    - `category_skill_enriched_base_payload_hash` string — Independent SHA-256 recomputation over the same base fields immediately after category-skill enrichment. Equality with category_skill_base_payload_hash proves shadow enrichment did not change funded inputs. Sports-edge-signals only.

## Other responses

- `400` — Invalid request parameter
- `401` — Missing or invalid API key
- `402` — Active Pro subscription required
- `403` — Account access denied
- `404` — Webhook endpoint not found
- `408` — The request timed out; reuse the same Idempotency-Key to learn whether it completed
- `409` — The previous signing secret is still in its bounded overlap window; retire it before preparing another staged secret. A keyed request can also return idempotency_in_progress while the same request is running.
- `422` — The Idempotency-Key was already used with a different request body
- `423` — Account is locked
- `429` — Rate limit exceeded
- `500` — Unexpected server error
- `503` — Redis-backed authenticated rate limiter unavailable

## Changes

- **2026-09-23** `0c2767401065` — 1 warning, 1 info
  - added the new `large_trade_inserted_v2` enum value to the `data/event_types/items/` response property for the response status `200`
  - added the required property `data/trade_filters` to the response with the `200` status
- **2026-09-23** `7e57bd9dc8b5` — 1 warning
  - added the new `sharp_money_flow_detected` enum value to the `data/event_types/items/` response property for the response status `200`
- **2026-09-23** `ece7a25b7a44` — 12 warning, 12 info
  - added the new `freshness_ceiling_unsatisfied` enum value to the `error/reason` response property for the response status `400`
  - added the new `freshness_ceiling_unsatisfied` enum value to the `error/reason` response property for the response status `401`
  - added the new `freshness_ceiling_unsatisfied` enum value to the `error/reason` response property for the response status `402`
  - added the new `freshness_ceiling_unsatisfied` enum value to the `error/reason` response property for the response status `403`
  - …20 more
- **2026-09-23** `cc7ab48fc929` — 2 warning
  - added the new `large_trades_inserted` enum value to the `data/event_types/items/` response property for the response status `200`
  - added the new `trader_synced` enum value to the `data/event_types/items/` response property for the response status `200`
- …earlier changes not shown

[Full history](https://skmtc.dev/0xinsider/apis/0xinsider-api/changes/api/v1/webhooks/:id/rotate-secret/prepare/post.md)

---

[API](https://skmtc.dev/0xinsider/apis/0xinsider-api.md) · [All operations](https://skmtc.dev/0xinsider/apis/0xinsider-api/llms.txt) · [OpenAPI document](https://skmtc.dev/0xinsider/apis/0xinsider-api/revisions/2035b3316329?raw)
