<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Speccy updates</title>
        <link>https://www.speccy.report/updates</link>
        <description>Release notes, migration guidance, design notes, and practical API documentation tips.</description>
        <lastBuildDate>Thu, 13 Aug 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Document workflows with links, prerequisites, and callbacks]]></title>
            <link>https://www.speccy.report/updates/links-and-prerequisites</link>
            <guid>https://www.speccy.report/updates/links-and-prerequisites</guid>
            <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Show readers what comes before an operation, what can follow its response, and which requests the API may send back.]]></description>
            <content:encoded><![CDATA[<p>An endpoint rarely stands alone. Creating a payment may require a customer, and its successful response may lead naturally to fetching, capturing, or refunding that payment. If those relationships exist only in prose, readers have to reconstruct the workflow themselves.</p>
<p>Speccy combines three complementary forms of operation relationship:</p>
<ul>
<li class="">OpenAPI links describe what a caller can do after a particular response.</li>
<li class=""><code>x-speccy-prerequisites</code> describes what must already have happened before the operation can be called.</li>
<li class="">OpenAPI callbacks describe requests the API may later send to the caller.</li>
</ul>
<p>Together they give an operation a useful sense of place: what gets you here, where can you go next, and what might come back to you?</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="use-links-for-response-driven-next-steps">Use links for response-driven next steps<a href="https://www.speccy.report/updates/links-and-prerequisites#use-links-for-response-driven-next-steps" class="hash-link" aria-label="Direct link to Use links for response-driven next steps" title="Direct link to Use links for response-driven next steps" translate="no">​</a></h2>
<p>OpenAPI's standard Link Object belongs to a response. This matters because the next operation often depends on both the response status and data returned in its body.</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#bfc7d5"><span class="token key atrule">paths</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">/payments</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">post</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> createPayment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">summary</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Create a payment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">responses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">'201'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Payment created</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">content</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token key atrule">application/json</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">schema</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token key atrule">$ref</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'#/components/schemas/Payment'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">links</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token key atrule">getPayment</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> getPayment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Read the payment that was just created.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">parameters</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token key atrule">paymentId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> $response.body</span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#/id</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  /payments/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">paymentId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> getPayment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">summary</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Get a payment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">parameters</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> paymentId</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">in</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> path</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">required</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">schema</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> string</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">responses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">'200'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Payment found</span><br></div></code></pre></div></div>
<p>The link says more than “these endpoints are related.” It says that <code>getPayment</code> becomes relevant after a <code>201</code>, and shows how the new payment ID flows into the next request.</p>
<p>Use a link when:</p>
<ul>
<li class="">The relationship begins with a specific response.</li>
<li class="">A value from that response supplies a parameter or request body value.</li>
<li class="">The linked operation is a likely next action, not a mandatory earlier step.</li>
</ul>
<p>Prefer <code>operationId</code> when both operations are in the same description. Use <code>operationRef</code> when you need a JSON Reference-style pointer to an operation. Keep operation IDs unique and stable so links survive changes to summaries and tags.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="use-prerequisites-for-earlier-requirements">Use prerequisites for earlier requirements<a href="https://www.speccy.report/updates/links-and-prerequisites#use-prerequisites-for-earlier-requirements" class="hash-link" aria-label="Direct link to Use prerequisites for earlier requirements" title="Direct link to Use prerequisites for earlier requirements" translate="no">​</a></h2>
<p>OpenAPI links point forward from a response, but OpenAPI has no matching object for “do this first.” Speccy's <code>x-speccy-prerequisites</code> extension fills that gap.</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#bfc7d5"><span class="token key atrule">paths</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">/customers</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">post</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> createCustomer</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">summary</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Create a customer</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">responses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">'201'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Customer created</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">/payments</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">post</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> createPayment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">summary</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Create a payment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">x-speccy-prerequisites</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> createCustomer</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Create the customer who will own the payment.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">responses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">'201'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Payment created</span><br></div></code></pre></div></div>
<p>Use a prerequisite when:</p>
<ul>
<li class="">Another operation creates a resource or state this request requires.</li>
<li class="">A setup, authorization, or verification step must be completed first.</li>
<li class="">Readers would otherwise discover the dependency only after a failed request.</li>
</ul>
<p>The shortest form is an operation ID:</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#bfc7d5"><span class="token key atrule">x-speccy-prerequisites</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> createCustomer</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> verifyCustomer</span><br></div></code></pre></div></div>
<p>Use the object form when the reason is not obvious:</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#bfc7d5"><span class="token key atrule">x-speccy-prerequisites</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> verifyCustomer</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Payments are available after identity verification succeeds.</span><br></div></code></pre></div></div>
<p>The description should explain the dependency, not repeat the linked operation's summary.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="use-callbacks-for-api-initiated-requests">Use callbacks for API-initiated requests<a href="https://www.speccy.report/updates/links-and-prerequisites#use-callbacks-for-api-initiated-requests" class="hash-link" aria-label="Direct link to Use callbacks for API-initiated requests" title="Direct link to Use callbacks for API-initiated requests" translate="no">​</a></h2>
<p>An OpenAPI Callback Object describes a request that the API may send after the original operation. Its key is a runtime expression that tells the API where to send that request, commonly using a callback URL supplied in the request body.</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#bfc7d5"><span class="token key atrule">paths</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">/payments</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">post</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> createPayment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">summary</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Create a payment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">callbacks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">paymentStatus</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">'{$request.body#/callbackUrl}'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token key atrule">post</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">summary</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Report payment status</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Reports the final status of the payment.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">requestBody</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token key atrule">required</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token key atrule">content</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                  </span><span class="token key atrule">application/json</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                    </span><span class="token key atrule">schema</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                      </span><span class="token key atrule">$ref</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'#/components/schemas/PaymentStatus'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">responses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token key atrule">'204'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                  </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Status received</span><br></div></code></pre></div></div>
<p>Speccy shows <code>Report payment status</code>, its <code>POST</code> method, and the <code>{$request.body#/callbackUrl}</code> expression in the collapsed workflow card. Below the main operation, it labels this as an API-initiated request, identifies the expression as the destination taken from the original request, and keeps the full callback contract collapsed until the reader opens it.</p>
<p>Use a callback when the API initiates a later HTTP request to a caller-provided URL. It uses HTTP, but it isn't another REST resource exposed by the API: the API temporarily becomes the client. Don't use one for polling, a client-initiated follow-up request, or a webhook whose destination isn't established by this operation. Top-level OpenAPI webhooks are a better fit for independently registered event subscriptions.</p>
<p>The runtime expression is part of the contract. Make sure it points to a value the original request supplies, and document callback authentication and retry behavior in the callback operation's description.</p>
<p>The built-in Luma Library API demonstrates this pattern on <code>createBook</code>: callers can supply a status callback URL, and Luma reports whether catalog indexing succeeded using a signed callback request. It also defines a top-level <code>book.indexed</code> webhook for subscribers that register once and receive catalog events across many requests.</p>
<p>Use <code>x-speccy-webhooks</code> when an operation emits a top-level webhook and readers need to move between them:</p>
<div class="language-yaml codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-yaml codeBlock_TAPP thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#bfc7d5"><span class="token key atrule">paths</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">/books</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">post</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> createBook</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">x-speccy-webhooks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> bookIndexed</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Emitted after catalog indexing finishes.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">webhooks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">book.indexed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">post</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">operationId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> bookIndexed</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">summary</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Book indexed</span><br></div></code></pre></div></div>
<p>Speccy shows the webhook under <strong>Events emitted</strong> on the triggering operation. On the webhook page, it derives the reverse <strong>Triggered by operations</strong> relationship from the same extension.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="use-all-three-to-describe-the-full-path">Use all three to describe the full path<a href="https://www.speccy.report/updates/links-and-prerequisites#use-all-three-to-describe-the-full-path" class="hash-link" aria-label="Direct link to Use all three to describe the full path" title="Direct link to Use all three to describe the full path" translate="no">​</a></h2>
<p>A payment workflow might read like this:</p>
<div class="language-text codeBlockContainer_ZGJx theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_kX1v"><pre tabindex="0" class="prism-code language-text codeBlock_TAPP thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_AdAo"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Create customer → Create payment → Get payment</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">       prerequisite ↑       │     ↑ 201 response link</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                          callback</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                             ↓</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                    Report payment status</span><br></div></code></pre></div></div>
<p>On the <code>createPayment</code> page, Speccy presents these relationships together as workflow context. The reader can move backward to required setup, forward to likely next operations, and see which requests the API may send back without searching the sidebar or opening several endpoint descriptions.</p>
<p>This is navigation and documentation, not orchestration. Links don't call the next operation, prerequisites don't enforce server-side state, and callbacks don't register or deliver themselves. The API must still validate requirements, store callback destinations safely, authenticate deliveries, and handle retries.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="keep-the-graph-useful">Keep the graph useful<a href="https://www.speccy.report/updates/links-and-prerequisites#keep-the-graph-useful" class="hash-link" aria-label="Direct link to Keep the graph useful" title="Direct link to Keep the graph useful" translate="no">​</a></h2>
<p>Document meaningful workflow edges, not every operation that happens to touch the same resource. A dense graph is just another form of noise.</p>
<p>A good relationship answers at least one concrete question:</p>
<ul>
<li class="">What must I create or complete before this call?</li>
<li class="">Which response makes the next call possible?</li>
<li class="">Which returned value do I pass to that call?</li>
<li class="">Where should I go to inspect or continue the result?</li>
<li class="">Which later request will the API send me, and where will it send it?</li>
</ul>
<p>Use tags and subgroups for broad organization. Use links, prerequisites, and callbacks for causal relationships between specific operations.</p>
<h2 class="anchor anchorTargetStickyNavbar_SAay" id="check-the-result">Check the result<a href="https://www.speccy.report/updates/links-and-prerequisites#check-the-result" class="hash-link" aria-label="Direct link to Check the result" title="Direct link to Check the result" translate="no">​</a></h2>
<p>Make sure every referenced <code>operationId</code> exists and is unique. Then open the operation page and verify that the workflow reads in the right direction, descriptions add useful context, response parameter expressions point to fields the response actually returns, and callback expressions point to values the original request supplies.</p>
<p>See <a class="" href="https://www.speccy.report/docs/openapi-extensions#operation-workflows">OpenAPI extensions</a> for the compact extension reference.</p>]]></content:encoded>
            <category>OpenAPI</category>
            <category>workflows</category>
        </item>
    </channel>
</rss>