HMAC webhook subscription linking

If you're not on Flip-Pay (or any other vendor we natively support),
host a /connect-mcp page on your own domain and POST back to us when
the reader's subscription is confirmed.

How it works

  1. Reader clicks "Already a subscriber?" in our consent screen or paywall
    upsell.
  2. We mint an installToken and 302 the reader to your
    subscriptionConnectUrl?install_token=…&return=….
  3. Your page checks the reader's session (logged in? subscribed?).
  4. If subscribed, your server POSTs /api/oauth/subscription-confirmed
    with an HMAC signature.
  5. We flip the SubscriptionLink row to confirmed, propagate
    tier=subscriber to tokens, and 302 the reader back to return.

Setup on your side (~1 afternoon)

  1. Generate a shared secret:
    openssl rand -base64 32
  2. Send it to us out-of-band so we can store it on your Publisher row.
  3. Build https://your-domain.com/connect-mcp to:
    • Read ?install_token=…&return=… from the URL.
    • Check your subscriber session.
    • On success, POST to https://api.oasy.ai/api/oauth/subscription-confirmed
      with body:
      {
        "install_token": "...",
        "status": "active",
        "email": "[email protected]"
      }
      and headers:
      x-oasy-signature: hmac-sha256 hex of the body using your secret
      content-type: application/json
    • 302 the reader to the return URL.
    • On failure, render an error and let the reader sign in or upgrade.

Setup on our side

UPDATE "Publisher"
SET "subscriptionConnectUrl"    = 'https://your-domain.com/connect-mcp',
    "subscriptionWebhookSecret" = '<the shared secret>'
WHERE id = '<your orgId>';

(Today this is a SQL update on our side; a dashboard UI is on the
roadmap.)

Cancellation

Same endpoint, status="cancelled":

{ "install_token": "...", "status": "cancelled" }

We downgrade all of the install's tokens to tier=free. Idempotent — re-sending
is harmless.

Reference implementation

We have a Next.js sample for /connect-mcp and the HMAC signing helper —
ping us and we'll share the gist.