[{"data":1,"prerenderedAt":940},["ShallowReactive",2],{"navigation":3,"/api/webhooks/delivery-and-retries":258,"/api/webhooks/delivery-and-retries-surround":935},[4,22,63,85,115,131,219,245],{"title":5,"path":6,"stem":7,"children":8,"page":21},"Getting Started","/getting-started","1.getting-started",[9,13,17],{"title":10,"path":11,"stem":12},"Introduction","/getting-started/introduction","1.getting-started/1.introduction",{"title":14,"path":15,"stem":16},"Quick Start","/getting-started/quick-start","1.getting-started/2.quick-start",{"title":18,"path":19,"stem":20},"Key Concepts","/getting-started/key-concepts","1.getting-started/3.key-concepts",false,{"title":23,"path":24,"stem":25,"children":26,"page":21},"Guides","/guides","2.guides",[27,31,35,39,43,47,51,55,59],{"title":28,"path":29,"stem":30},"Quick Share Guide","/guides/quick-share","2.guides/1.quick-share",{"title":32,"path":33,"stem":34},"Slack Integration","/guides/slack-integration","2.guides/2.slack-integration",{"title":36,"path":37,"stem":38},"Enterprise Setup","/guides/enterprise-setup","2.guides/3.enterprise-setup",{"title":40,"path":41,"stem":42},"Creating a Share","/guides/creating-a-share","2.guides/4.creating-a-share",{"title":44,"path":45,"stem":46},"Zero-Knowledge Custody","/guides/zero-knowledge-custody","2.guides/5.zero-knowledge-custody",{"title":48,"path":49,"stem":50},"Secure Requests","/guides/secure-requests","2.guides/6.secure-requests",{"title":52,"path":53,"stem":54},"Receiving a Secure Request","/guides/receiving-a-secure-request","2.guides/7.receiving-a-secure-request",{"title":56,"path":57,"stem":58},"SecurePaste","/guides/securepaste","2.guides/8.securepaste",{"title":60,"path":61,"stem":62},"Notifications","/guides/notifications","2.guides/9.notifications",{"title":64,"icon":65,"path":66,"stem":67,"children":68,"page":21},"Account","i-lucide-user-cog","/account","3.account",[69,73,77,81],{"title":70,"path":71,"stem":72},"Signing In","/account/signing-in","3.account/1.signing-in",{"title":74,"path":75,"stem":76},"Plans and Share Allowance","/account/plans-and-share-allowance","3.account/2.plans-and-share-allowance",{"title":78,"path":79,"stem":80},"Billing and Subscription","/account/billing-and-subscription","3.account/3.billing-and-subscription",{"title":82,"path":83,"stem":84},"Plans and Limits","/account/plans-and-limits","3.account/4.plans-and-limits",{"title":86,"icon":87,"path":88,"stem":89,"children":90,"page":21},"Teams","i-lucide-users","/teams","4.teams",[91,95,99,103,107,111],{"title":92,"path":93,"stem":94},"Teams and Contexts","/teams/teams-and-contexts","4.teams/1.teams-and-contexts",{"title":96,"path":97,"stem":98},"Members, Roles and Seats","/teams/members-roles-and-seats","4.teams/2.members-roles-and-seats",{"title":100,"path":101,"stem":102},"Joining a Team","/teams/joining-a-team","4.teams/3.joining-a-team",{"title":104,"path":105,"stem":106},"Custom Branding","/teams/custom-branding","4.teams/4.custom-branding",{"title":108,"path":109,"stem":110},"Policy and Audit","/teams/policy-and-audit","4.teams/5.policy-and-audit",{"title":112,"path":113,"stem":114},"Zero-Knowledge for Teams","/teams/zero-knowledge-for-teams","4.teams/6.zero-knowledge-for-teams",{"title":116,"path":117,"stem":118,"children":119,"icon":130},"Help","/help","5.help/0.index",[120,122,126],{"title":121,"path":117,"stem":118},"Help and Support",{"title":123,"path":124,"stem":125},"Link Not Working","/help/link-not-working","5.help/1.link-not-working",{"title":127,"path":128,"stem":129},"Error Messages","/help/error-messages","5.help/2.error-messages","i-lucide-life-buoy",{"title":132,"path":133,"stem":134,"children":135},"API Reference","/api","6.api/0.index",[136,137,141,167,189,193,211,215],{"title":132,"path":133,"stem":134},{"title":138,"path":139,"stem":140},"Authentication","/api/authentication","6.api/1.authentication",{"title":142,"path":143,"stem":144,"children":145},"Shares","/api/shares","6.api/2.shares/0.index",[146,147,151,155,159,163],{"title":142,"path":143,"stem":144},{"title":148,"path":149,"stem":150},"Create a share","/api/shares/create","6.api/2.shares/1.create",{"title":152,"path":153,"stem":154},"List shares","/api/shares/list","6.api/2.shares/2.list",{"title":156,"path":157,"stem":158},"Retrieve a share","/api/shares/retrieve","6.api/2.shares/3.retrieve",{"title":160,"path":161,"stem":162},"Expire a share","/api/shares/delete","6.api/2.shares/4.delete",{"title":164,"path":165,"stem":166},"Client-side encryption","/api/shares/client-side-encryption","6.api/2.shares/5.client-side-encryption",{"title":168,"path":169,"stem":170,"children":171},"Secure requests","/api/requests","6.api/3.requests/0.index",[172,173,177,181,185],{"title":168,"path":169,"stem":170},{"title":174,"path":175,"stem":176},"Create a request","/api/requests/create","6.api/3.requests/1.create",{"title":178,"path":179,"stem":180},"List and retrieve requests","/api/requests/list","6.api/3.requests/2.list",{"title":182,"path":183,"stem":184},"Read submissions","/api/requests/submissions","6.api/3.requests/3.submissions",{"title":186,"path":187,"stem":188},"Expire or delete a request","/api/requests/delete","6.api/3.requests/4.delete",{"title":190,"path":191,"stem":192},"Stats","/api/stats","6.api/4.stats",{"title":194,"path":195,"stem":196,"children":197},"Webhooks","/api/webhooks","6.api/5.webhooks/0.index",[198,199,203,207],{"title":194,"path":195,"stem":196},{"title":200,"path":201,"stem":202},"Event reference","/api/webhooks/events","6.api/5.webhooks/1.events",{"title":204,"path":205,"stem":206},"Verifying signatures","/api/webhooks/verifying-signatures","6.api/5.webhooks/2.verifying-signatures",{"title":208,"path":209,"stem":210},"Delivery and retries","/api/webhooks/delivery-and-retries","6.api/5.webhooks/3.delivery-and-retries",{"title":212,"path":213,"stem":214},"MCP server","/api/mcp","6.api/6.mcp",{"title":216,"path":217,"stem":218},"Errors and Rate Limits","/api/errors-and-limits","6.api/7.errors-and-limits",{"title":220,"path":221,"stem":222,"children":223},"SDKs","/sdks","7.sdks/0.index",[224,225,229,233,237,241],{"title":220,"path":221,"stem":222},{"title":226,"path":227,"stem":228},"Node SDK","/sdks/node","7.sdks/1.node",{"title":230,"path":231,"stem":232},"Python SDK","/sdks/python","7.sdks/2.python",{"title":234,"path":235,"stem":236},"Go SDK","/sdks/go","7.sdks/3.go",{"title":238,"path":239,"stem":240},"Rust SDK","/sdks/rust","7.sdks/4.rust",{"title":242,"path":243,"stem":244},"Conformance vectors","/sdks/conformance-vectors","7.sdks/5.conformance-vectors",{"title":246,"path":247,"stem":248,"children":249,"page":21},"Security","/security","8.security",[250,254],{"title":251,"path":252,"stem":253},"Encryption","/security/encryption","8.security/1.encryption",{"title":255,"path":256,"stem":257},"Compliance","/security/compliance","8.security/2.compliance",{"id":259,"title":208,"api":260,"body":261,"description":929,"extension":930,"links":260,"meta":931,"navigation":932,"path":209,"seo":933,"stem":210,"__hash__":934},"docs/6.api/5.webhooks/3.delivery-and-retries.md",null,{"type":262,"value":263,"toc":914},"minimark",[264,268,273,281,364,378,381,391,394,397,424,432,436,443,446,527,545,569,573,580,652,662,670,675,680,690,694,701,704,740,743,749,754,758,767,770,835,839,856,863,868,872,881,887,892,895],[265,266,267],"p",{},"Events are queued when they happen and sent by a background worker, so delivery is not synchronous with the action that caused it. Emission is fire-and-forget on CredenShare's side: if your endpoint is unreachable, the share, request or membership change that triggered the event still succeeds.",[269,270,272],"h2",{"id":271},"the-request","The request",[265,274,275,276,280],{},"CredenShare sends a ",[277,278,279],"code",{},"POST"," to the URL you registered, with a JSON body.",[282,283,284,297],"table",{},[285,286,287],"thead",{},[288,289,290,294],"tr",{},[291,292,293],"th",{},"Header",[291,295,296],{},"Value",[298,299,300,313,325,338,348],"tbody",{},[288,301,302,308],{},[303,304,305],"td",{},[277,306,307],{},"Content-Type",[303,309,310],{},[277,311,312],{},"application/json",[288,314,315,320],{},[303,316,317],{},[277,318,319],{},"User-Agent",[303,321,322],{},[277,323,324],{},"CredenShare-Webhooks/1",[288,326,327,332],{},[303,328,329],{},[277,330,331],{},"X-CredenShare-Event",[303,333,334,335],{},"The event code, for example ",[277,336,337],{},"share.created",[288,339,340,345],{},[303,341,342],{},[277,343,344],{},"X-CredenShare-Delivery",[303,346,347],{},"The delivery's id, a UUID",[288,349,350,355],{},[303,351,352],{},[277,353,354],{},"X-CredenShare-Signature",[303,356,357,360,361],{},[277,358,359],{},"t=\u003Cunix-seconds>,v1=\u003Chex>"," — see ",[362,363,204],"a",{"href":205},[265,365,366,367,370,371,370,374,377],{},"Standard HTTP headers (",[277,368,369],{},"Host",", ",[277,372,373],{},"Content-Length",[277,375,376],{},"Accept-Encoding",") are set by the HTTP client as usual. You cannot add headers of your own, change the method, or change the content type; an endpoint's URL is also fixed once created.",[265,379,380],{},"A delivery on the wire takes this shape:",[382,383,389],"pre",{"className":384,"code":386,"language":387,"meta":388},[385],"language-text","POST /your-webhook-path HTTP/1.1\nHost: hooks.example.com\nContent-Type: application/json\nUser-Agent: CredenShare-Webhooks/1\nX-CredenShare-Event: share.deleted\nX-CredenShare-Delivery: 3f1b9c74-5e2a-4b6d-9c88-1a0e7d452fb1\nX-CredenShare-Signature: t=\u003Cunix-seconds>,v1=\u003Chex>\n\n\u003Cflat, metadata-only JSON carrying an \"event\" key>\n","text","",[277,390,386],{"__ignoreMap":388},[265,392,393],{},"Do not assume a particular key order or spacing in the body. Read it as JSON, and if you are verifying the signature, hash the bytes you received rather than anything you re-serialize.",[265,395,396],{},"A few consequences worth designing around:",[398,399,400,412,418],"ul",{},[401,402,403,407,408,411],"li",{},[404,405,406],"strong",{},"Redirects are not followed."," A ",[277,409,410],{},"3xx"," is treated as a failed attempt, not as a pointer to somewhere else. Register the final URL.",[401,413,414,417],{},[404,415,416],{},"HTTPS only",", and the hostname must resolve to a public address. This is re-checked before every delivery, not only at registration.",[401,419,420,423],{},[404,421,422],{},"Each attempt times out after 10 seconds"," — both connecting and the request as a whole.",[425,426,429],"callout",{"color":427,"icon":428},"info","i-lucide-info",[265,430,431],{},"Ten seconds is not much room. Verify the signature, write the event somewhere durable, respond, and do the real work afterwards. A receiver that processes inline will start timing out as soon as its own dependencies slow down, and every timeout costs you a retry.",[269,433,435],{"id":434},"what-counts-as-success","What counts as success",[265,437,438,439,442],{},"Any ",[277,440,441],{},"2xx"," status. The response body is ignored.",[265,444,445],{},"Anything else is a failed attempt, and what happens next depends on the status:",[282,447,448,458],{},[285,449,450],{},[288,451,452,455],{},[291,453,454],{},"Response",[291,456,457],{},"What CredenShare does",[298,459,460,473,487,501,510,519],{},[288,461,462,466],{},[303,463,464],{},[277,465,441],{},[303,467,468,469,472],{},"Marks the delivery ",[404,470,471],{},"delivered",". Done.",[288,474,475,484],{},[303,476,477,480,481],{},[277,478,479],{},"408"," or ",[277,482,483],{},"429",[303,485,486],{},"Retries on the schedule below.",[288,488,489,495],{},[303,490,491,492],{},"Any other ",[277,493,494],{},"4xx",[303,496,468,497,500],{},[404,498,499],{},"dead"," immediately. No further attempts, however many were left.",[288,502,503,508],{},[303,504,505],{},[277,506,507],{},"5xx",[303,509,486],{},[288,511,512,516],{},[303,513,514],{},[277,515,410],{},[303,517,518],{},"Not followed. Counts as a failed attempt and is retried.",[288,520,521,524],{},[303,522,523],{},"Timeout, connection refused, TLS failure",[303,525,526],{},"Retried.",[265,528,529,530,532,533,535,536,538,539,541,542,544],{},"The reasoning behind the ",[277,531,494],{}," rule: a ",[277,534,494],{}," says the request itself is unacceptable, and CredenShare will send a byte-identical request on the next attempt, so repeating it cannot help. ",[277,537,479],{}," and ",[277,540,483],{}," are the two ",[277,543,494],{}," codes that mean \"the request was fine, try it again later\", so they stay on the schedule.",[425,546,549],{"color":547,"icon":548},"warning","i-lucide-alert-triangle",[265,550,551,552,555,556,558,559,562,563,565,566,568],{},"This makes ",[277,553,554],{},"400"," an expensive default for rejecting a delivery. If your receiver returns ",[277,557,554],{}," for a signature mismatch, a temporary misconfiguration on your side turns every event that arrives during it into a permanent loss. Return ",[277,560,561],{},"500"," (or ",[277,564,483],{},") for anything you expect to be able to fix, and reserve ",[277,567,494],{}," for a request you genuinely never want again.",[269,570,572],{"id":571},"the-retry-schedule","The retry schedule",[265,574,575,576,579],{},"A delivery gets at most ",[404,577,578],{},"6 HTTP attempts",". Each wait is five times the last, capped at six hours:",[282,581,582,595],{},[285,583,584],{},[288,585,586,589,592],{},[291,587,588],{},"After attempt",[291,590,591],{},"Wait",[291,593,594],{},"Elapsed since the first attempt",[298,596,597,608,619,630,641],{},[288,598,599,602,605],{},[303,600,601],{},"1",[303,603,604],{},"1 minute",[303,606,607],{},"1m",[288,609,610,613,616],{},[303,611,612],{},"2",[303,614,615],{},"5 minutes",[303,617,618],{},"6m",[288,620,621,624,627],{},[303,622,623],{},"3",[303,625,626],{},"25 minutes",[303,628,629],{},"31m",[288,631,632,635,638],{},[303,633,634],{},"4",[303,636,637],{},"2 hours 5 minutes",[303,639,640],{},"2h 36m",[288,642,643,646,649],{},[303,644,645],{},"5",[303,647,648],{},"6 hours",[303,650,651],{},"8h 36m",[265,653,654,655,658,659,661],{},"So the sixth and final attempt lands roughly ",[404,656,657],{},"8 hours 36 minutes"," after the first. After it fails, the delivery is marked ",[277,660,499],{}," and left alone.",[265,663,664,665,669],{},"Two things affect when the ",[666,667,668],"em",{},"first"," attempt arrives. The worker sweeps the queue once a minute, so expect up to about a minute between the event and the first attempt. Each sweep takes a bounded batch (currently up to 50 deliveries) and works through it one at a time, so a burst of events can take a few minutes to clear.",[425,671,672],{"color":427,"icon":428},[265,673,674],{},"There is no ordering guarantee. Retries alone break ordering — a delivery that fails and succeeds an hour later arrives after events that happened long afterwards. If order matters to your logic, derive it from the state you fetch, not from arrival sequence.",[676,677,679],"h3",{"id":678},"duplicates","Duplicates",[265,681,682,683,685,686,689],{},"Deduplicate on ",[277,684,344],{},". Retries of the same delivery reuse the same id, so a receiver that acknowledged after its own timeout can recognise the repeat. A ",[404,687,688],{},"replay"," is a new delivery and gets a new id, which is deliberate: a replay is a request for the event to be handled again.",[269,691,693],{"id":692},"when-an-endpoint-is-disabled","When an endpoint is disabled",[265,695,696,697,700],{},"Repeated failures do ",[404,698,699],{},"not"," disable your endpoint. There is no failure threshold, no automatic pause and no cool-off. Deliveries die individually, and new events keep being queued and attempted.",[265,702,703],{},"CredenShare disables an endpoint by itself in exactly two situations:",[282,705,706,716],{},[285,707,708],{},[288,709,710,713],{},[291,711,712],{},"Trigger",[291,714,715],{},"What happens",[298,717,718,729],{},[288,719,720,723],{},[303,721,722],{},"The endpoint's hostname resolves to a private, loopback or otherwise reserved address at delivery time",[303,724,725,726,728],{},"That delivery is marked ",[277,727,499],{}," and the endpoint is disabled with a reason recorded against it",[288,730,731,734],{},[303,732,733],{},"The endpoint's signing secret can no longer produce verifiable signatures, because the underlying signing key changed",[303,735,736,737,739],{},"Deliveries are marked ",[277,738,499],{}," and the endpoint is disabled with a reason telling you to re-create it",[265,741,742],{},"Both cases record a reason against the endpoint, reported alongside its disabled state. For the first, make the hostname resolve to a public address again and re-enable the endpoint from the app; because an endpoint's URL cannot be changed after creation, an endpoint pointing at a name you cannot fix has to be replaced. For the second, rotating the secret will not help — create a new endpoint and configure your receiver with its new secret.",[265,744,745,746,748],{},"You can also disable an endpoint yourself, from the ",[404,747,194],{}," card in your account's Security settings. A disabled endpoint stops receiving immediately: events that occur while it is disabled are not queued for it and cannot be replayed later, because no delivery was ever created.",[425,750,751],{"color":547,"icon":548},[265,752,753],{},"A disabled endpoint still counts against your plan's endpoint limit. Disabling one does not free a slot — only removing it does.",[269,755,757],{"id":756},"dead-deliveries-the-delivery-log-and-replay","Dead deliveries, the delivery log, and replay",[265,759,760,761,763,764,766],{},"There is no dead-letter queue and no separate failure notification. A delivery that exhausts its attempts, or that a ",[277,762,494],{}," killed outright, simply stays in the endpoint's delivery log with the status ",[277,765,499],{},". Recovery is a deliberate act: you look at the log and replay what you want.",[265,768,769],{},"A delivery moves through these states:",[282,771,772,782],{},[285,773,774],{},[288,775,776,779],{},[291,777,778],{},"Status",[291,780,781],{},"Meaning",[298,783,784,794,804,816,826],{},[288,785,786,791],{},[303,787,788],{},[277,789,790],{},"pending",[303,792,793],{},"Queued, first attempt not yet made",[288,795,796,801],{},[303,797,798],{},[277,799,800],{},"delivering",[303,802,803],{},"An attempt is in flight",[288,805,806,810],{},[303,807,808],{},[277,809,471],{},[303,811,812,813,815],{},"A ",[277,814,441],{}," was received",[288,817,818,823],{},[303,819,820],{},[277,821,822],{},"failed",[303,824,825],{},"An attempt failed and another is scheduled",[288,827,828,832],{},[303,829,830],{},[277,831,499],{},[303,833,834],{},"No further attempts will be made",[676,836,838],{"id":837},"reading-the-log","Reading the log",[265,840,841,842,844,845,847,848,851,852,855],{},"Open your account page, go to the ",[404,843,246],{}," tab, find the ",[404,846,194],{}," card, and choose ",[404,849,850],{},"Deliveries"," on the endpoint you care about. The table shows the event code, the status, the number of attempts, the HTTP status code your endpoint last returned, when the delivery was created, and a ",[404,853,854],{},"Replay"," action. It lists the 50 most recent deliveries, newest first.",[265,857,858,859,862],{},"The delivery record also retains the error text of the last failure and the payload that was sent, which is what makes a failure diagnosable after the fact: you can see whether your endpoint answered ",[277,860,861],{},"502",", timed out, or rejected the request outright.",[425,864,865],{"color":427,"icon":428},[265,866,867],{},"Webhook management — creating, editing, disabling and removing endpoints, plus the delivery log and replay — lives in the app and is authenticated by your session, not by an API key. That is deliberate: a leaked API key that could re-point a webhook would turn one stolen credential into an ongoing feed of event metadata. Through the API surface, the hosted MCP server can list your endpoints and rotate a secret, and nothing else.",[676,869,871],{"id":870},"replaying","Replaying",[265,873,874,876,877,880],{},[404,875,854],{}," creates a new delivery carrying the ",[404,878,879],{},"original payload, verbatim",". Your endpoint receives what it missed, not the current state of the object — which is the point, but it means the payload can describe something that has since changed or been deleted. Treat a replayed event as a record of what happened, and fetch current state if you need it.",[265,882,883,884,886],{},"The original delivery's attempt history is left intact, so the log keeps showing what actually failed. The replay is a fresh delivery: it gets its own ",[277,885,344],{}," id, its own signature and timestamp, and its own six attempts.",[425,888,889],{"color":547,"icon":548},[265,890,891],{},"Removing an endpoint hard-deletes its entire delivery log along with it. There is no recovery and nothing left to replay. If you are replacing an endpoint, replay anything you still need before removing the old one.",[893,894],"hr",{},[425,896,898],{"color":427,"icon":897},"i-lucide-arrow-right",[265,899,900,901,907,908,913],{},"Retry windows and delivery history are the same on every paid plan. ",[362,902,906],{"href":903,"rel":904},"https://credenshare.io/pricing",[905],"nofollow","Compare plans",", or ",[362,909,912],{"href":910,"rel":911},"https://credenshare.io/enterprise",[905],"ask about a stricter SLA",".",{"title":388,"searchDepth":915,"depth":916,"links":917},1,2,[918,919,920,924,925],{"id":271,"depth":916,"text":272},{"id":434,"depth":916,"text":435},{"id":571,"depth":916,"text":572,"children":921},[922],{"id":678,"depth":923,"text":679},3,{"id":692,"depth":916,"text":693},{"id":756,"depth":916,"text":757,"children":926},[927,928],{"id":837,"depth":923,"text":838},{"id":870,"depth":923,"text":871},"The request CredenShare sends, what counts as success, the retry schedule, and how to recover a delivery that failed.","md",{},true,{"title":208,"description":929},"XK_asG78SIzT-M1aRWLlnKJO9fKmWCJRwdepLEOkgPc",[936,938],{"title":204,"path":205,"stem":206,"description":937,"children":-1},"How CredenShare signs every webhook delivery, and how to verify one correctly.",{"title":212,"path":213,"stem":214,"description":939,"children":-1},"Connect an AI assistant to CredenShare over the Model Context Protocol, without a plaintext secret ever reaching the model.",1788908853434]