{
  "slug": "stripe-customer-portal-sessions-support-recovery-after-expiration-55cf232d23f7",
  "title": "Stripe customer portal sessions support recovery after expiration",
  "tools": [
    "stripe"
  ],
  "tags": [
    "agent"
  ],
  "introduced_at": "2026-09-30T00:00:00.000Z",
  "announced_at": "2026-09-30T00:00:00.000Z",
  "effective_at": null,
  "date_basis": "source-publication",
  "status": "unknown",
  "how": {
    "incantation": "When creating a portal session that should be recoverable after expiration, set `after_expiration[type]` to `customer_login`. Customers can verify their email and receive a replacement session using the original URL; set `after_expiration[customer_login][expires_at]` to limit recovery.",
    "examples": [
      "curl https://api.stripe.com/v1/billing_portal/sessions \\\n  -u \"<YOUR_SECRET_KEY>:\" \\\n  -H \"Stripe-Version: 2026-09-30.preview\" \\\n  -d \"customer=<CUSTOMER_ID>\" \\\n  --data-urlencode \"return_url=https://example.com/account\" \\\n  -d \"after_expiration[type]\"=customer_login",
      "curl https://api.stripe.com/v1/billing_portal/sessions \\\n  -u \"<YOUR_SECRET_KEY>:\" \\\n  -H \"Stripe-Version: 2026-09-30.preview\" \\\n  -d \"customer=<CUSTOMER_ID>\" \\\n  --data-urlencode \"return_url=https://example.com/account\" \\\n  -d \"after_expiration[type]\"=customer_login \\\n  -d \"after_expiration[customer_login][expires_at]\"=<UNIX_TIMESTAMP>"
    ],
    "gotchas": [
      "Availability: API version 2026-09-30.preview",
      "customer (required): ID of an existing customer.",
      "return_url: Redirect destination when the customer returns to your site; required if no default return URL is set in the Dashboard configuration.",
      "after_expiration: Set when creating each portal session to configure behavior after expiration.",
      "after_expiration.type (required): Set to `customer_login` to allow customers to verify their email and receive a replacement session with the same configuration.",
      "after_expiration.customer_login.expires_at: Timestamp deadline for recovery. If omitted, recovery is available at any time after the session expires.",
      "Prerequisite: Create a customer before creating the portal session.",
      "Prerequisite: Authenticate customers on your site before creating sessions for them.",
      "Prerequisite: Use the customer ID and a `return_url`; `return_url` is required when the Dashboard configuration has no default return URL.",
      "Session recovery is enabled by setting `after_expiration` when creating each portal session.",
      "If `expires_at` is omitted, customers can recover the session at any time after it expires."
    ]
  },
  "why_it_matters": "Let customers reopen the customer portal from an existing session URL after that session expires.",
  "sources": [
    "https://docs.stripe.com/changelog/endive/2026-09-30/adds-session-recovery-for-expired-customer-portal-sessions",
    "https://docs.stripe.com/api/customer_portal/sessions/create?api-version=2026-09-30.preview",
    "https://docs.stripe.com/customer-management/integrate-customer-portal"
  ],
  "rank": 0.96027,
  "judge": {
    "publish": true,
    "judge_model": "codex-cli/gpt-6-luna+typesafe/jev-1.13.0",
    "prompt_version": "extract-v7+enrich-v2+judge-v2x3+jev-publish-v1"
  },
  "review_state": "approved",
  "provenance": {
    "run_id": "wave1b-tools-20261017",
    "verdict_id": "wave1b-tools-20261017:wave1b-tools-20261017-92ae9ef07b58c900-0:gate",
    "evidence_hash": "54fd393522623b0f50f28f2bc02d7ea8486e0807eaa0934acfba3433ac888670"
  },
  "review": {
    "draft_hash": "e5d8742f1cf7dbfdd5d3707dab0f7f36e1e71b1802f2d5b4fbad02280f9b8641",
    "reviewer": "publication-gate",
    "reviewed_at": "2026-10-07T00:00:00.000Z",
    "decision": "wave1b-tools-20261017:gate",
    "reason": "3 of 3 judge runs approved with p_yes >= 0.9 (mean 0.96 >= 0.9; 2 needed) and Jev gave 0.71 (>= 0.6 needed)."
  }
}
