{"id":6186,"date":"2026-02-13T18:34:54","date_gmt":"2026-02-13T23:34:54","guid":{"rendered":"https:\/\/chubes.net\/?documentation=webhook"},"modified":"2026-02-13T20:19:23","modified_gmt":"2026-02-14T01:19:23","slug":"webhook","status":"publish","type":"documentation","link":"https:\/\/chubes.net\/docs\/spawn\/inc\/webhook\/","title":{"rendered":"Webhook"},"content":{"rendered":"<h2 class=\"wp-block-heading\">Overview<\/h2><p>Handles incoming webhooks for provisioning (Sweatpants) and Stripe events via the stripe-integration plugin.<\/p><h2 class=\"wp-block-heading\">Routes<\/h2><h3 class=\"wp-block-heading\">POST \/spawn\/v1\/webhook\/provisioner<\/h3><p>Processes Sweatpants callbacks.<\/p><p>Headers:<\/p><ul class=\"wp-block-list\"><li><code>X-Spawn-Internal-Key<\/code> (string)<\/li><li><code>Authorization: Bearer &lt;token&gt;<\/code> (Sweatpants token)<\/li><\/ul><div class=\"code-block-wrapper\"><div class=\"code-block-header\"><span class=\"code-block-language\">php<\/span><button class=\"code-copy-btn\" aria-label=\"Copy code\"><svg><use href=\"https:\/\/chubes.net\/wp-content\/themes\/chubes\/assets\/icons\/chubes.svg#icon-copy\"><\/use><\/svg><\/button><\/div><pre data-chubes-enhanced class=\"wp-block-code language-php\"><code class=\"language-php\">register_rest_route(\n\t&#039;spawn\/v1&#039;,\n\t&#039;\/webhook\/provisioner&#039;,\n\t[\n\t\t&#039;methods&#039;  =&gt; &#039;POST&#039;,\n\t\t&#039;callback&#039; =&gt; [ __CLASS__, &#039;handle_provisioner_webhook&#039; ],\n\t]\n);<\/code><\/pre><\/div><h2 class=\"wp-block-heading\">Stripe Webhook Handlers<\/h2><p>These are triggered by the stripe-integration plugin:<\/p><ul class=\"wp-block-list\"><li><code>handle_checkout_completed( $session, $event )<\/code><\/li><li><code>handle_invoice_paid( $invoice, $event )<\/code><\/li><li><code>handle_payment_failed( $invoice, $event )<\/code><\/li><li><code>handle_subscription_cancelled( $subscription, $event )<\/code><\/li><\/ul><h2 class=\"wp-block-heading\">Methods<\/h2><ul class=\"wp-block-list\"><li><code>init(): void<\/code> registers routes and Stripe webhook hooks.<\/li><li><code>register_routes(): void<\/code> registers the provisioner endpoint.<\/li><li><code>verify_provisioner_webhook( WP_REST_Request $request ): bool|WP_Error<\/code> validates webhook headers.<\/li><li><code>handle_provisioner_webhook( WP_REST_Request $request ): WP_REST_Response|WP_Error<\/code> processes <code>provisioning_complete<\/code>.<\/li><li><code>handle_checkout_completed( $session, $event ): void<\/code> routes credit purchases, domain renewals, or subscription checkouts.<\/li><li><code>handle_invoice_paid( $invoice, $event ): void<\/code> marks subscription active and updates renewal time.<\/li><li><code>handle_payment_failed( $invoice, $event ): void<\/code> updates status to <code>payment_failed<\/code>.<\/li><li><code>handle_subscription_cancelled( $subscription, $event ): void<\/code> schedules deletion and sends cancellation email.<\/li><\/ul><h2 class=\"wp-block-heading\">Hooks and Filters<\/h2><ul class=\"wp-block-list\"><li><code>stripe_integration_webhook_checkout_session_completed<\/code><\/li><li><code>stripe_integration_webhook_invoice_paid<\/code><\/li><li><code>stripe_integration_webhook_invoice_payment_failed<\/code><\/li><li><code>stripe_integration_webhook_customer_subscription_deleted<\/code><\/li><\/ul>","protected":false},"excerpt":{"rendered":"<p>Overview Handles incoming webhooks for provisioning (Sweatpants) and Stripe events via the stripe-integration plugin. Routes POST \/spawn\/v1\/webhook\/provisioner Processes Sweatpants callbacks. Headers: X-Spawn-Internal-Key (string) Authorization: Bearer &lt;token&gt; (Sweatpants token) register_rest_route( &#8216;spawn\/v1&#8217;,&#8230;<\/p>\n","protected":false},"featured_media":0,"template":"","meta":{"footnotes":""},"tags":[],"project":[772],"project_type":[485],"class_list":["post-6186","documentation","type-documentation","status-publish","hentry","project-inc","project_type-tools"],"project_info":{"id":765,"name":"Spawn","slug":"spawn"},"project_type_info":{"id":484,"name":"WordPress Plugins","slug":"wordpress-plugins"},"_links":{"self":[{"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/documentation\/6186","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/documentation"}],"about":[{"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/types\/documentation"}],"version-history":[{"count":3,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/documentation\/6186\/revisions"}],"predecessor-version":[{"id":8650,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/documentation\/6186\/revisions\/8650"}],"wp:attachment":[{"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/media?parent=6186"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/tags?post=6186"},{"taxonomy":"project","embeddable":true,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/project?post=6186"},{"taxonomy":"project_type","embeddable":true,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/project_type?post=6186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}