diff --git a/fern/products/api-def/ferndef/endpoints/sse.mdx b/fern/products/api-def/ferndef/endpoints/sse.mdx
index 48d553ee4..75d2c1583 100644
--- a/fern/products/api-def/ferndef/endpoints/sse.mdx
+++ b/fern/products/api-def/ferndef/endpoints/sse.mdx
@@ -69,6 +69,28 @@ types:
Generated SDKs expose each event's [metadata — event ID, event type, and retry interval](/learn/sdks/deep-dives/sse-metadata) to your end users.
+### Resumable streams
+
+Set `resumable: true` on `response-stream` to opt an SSE endpoint into [automatic reconnection](/learn/sdks/deep-dives/sse-metadata#automatic-reconnection). When the connection drops mid-stream, the generated SDK reconnects and resends the last event ID in the `Last-Event-ID` header, so a server that supports that header resumes where the stream left off.
+
+```yaml title="chat.yml" {10}
+service:
+ base-path: /chat
+ endpoints:
+ stream:
+ method: POST
+ path: ""
+ response-stream:
+ type: Chat
+ format: sse
+ resumable: true
+
+types:
+ Chat:
+ properties:
+ text: string
+```
+
## `Stream` parameter
It has become common practice for endpoints to have a `stream` parameter that
diff --git a/fern/products/api-def/openapi/endpoints/sse.mdx b/fern/products/api-def/openapi/endpoints/sse.mdx
index 0f853f2e5..53aed0df2 100644
--- a/fern/products/api-def/openapi/endpoints/sse.mdx
+++ b/fern/products/api-def/openapi/endpoints/sse.mdx
@@ -90,6 +90,38 @@ paths:
# ... responses and schemas
```
+### Resumable streams
+
+Set `resumable: true` to opt an SSE endpoint into [automatic reconnection](/learn/sdks/deep-dives/sse-metadata#automatic-reconnection). When the connection drops mid-stream, the generated SDK reconnects and resends the last event ID in the `Last-Event-ID` header, so a server that supports that header resumes where the stream left off.
+
+```yaml title="openapi.yml" {4-7}
+paths:
+ /logs:
+ post:
+ x-fern-streaming:
+ format: sse
+ terminator: "[DONE]"
+ resumable: true
+# ... responses and schemas
+```
+
+Configure a [`terminator`](#terminator-message) alongside `resumable`. The terminator marks a stream as complete, letting the SDK distinguish a finished stream from a dropped connection so it reconnects only on genuine drops.
+
+`resumable` is inheritable. Set it at the document level to apply to every SSE endpoint, and override it on individual operations:
+
+```yaml title="openapi.yml"
+x-fern-streaming:
+ resumable: true # applies to all SSE endpoints
+
+paths:
+ /logs:
+ post:
+ x-fern-streaming:
+ format: sse
+ resumable: false # overrides the document default
+# ... responses and schemas
+```
+
## `Stream` parameter
It has become common practice for endpoints to have a `stream` parameter that
diff --git a/fern/products/sdks/capabilities.mdx b/fern/products/sdks/capabilities.mdx
index 98322abca..ffb52c397 100644
--- a/fern/products/sdks/capabilities.mdx
+++ b/fern/products/sdks/capabilities.mdx
@@ -257,7 +257,7 @@ Fern SDKs include the following capabilities:
- **Retries with backoff**: Automatically retry failed requests with exponential backoff. [Learn more](/sdks/deep-dives/retries-with-backoff)
- **Webhook signature verification**: Verify the signature of incoming webhook requests. [Learn more](/learn/sdks/deep-dives/webhook-signature-verification)
- **Idempotency headers**: Built-in protection against duplicate submissions. [Learn more](/sdks/deep-dives/idempotency)
-- **Server-sent events**: Stream JSON data from your server to your client, with opt-in access to [SSE metadata](/learn/sdks/deep-dives/sse-metadata) (event ID, event type, retry). [Learn more](/learn/sdks/deep-dives/sse-metadata)
+- **Server-sent events**: Stream JSON data from your server to your client, with opt-in access to [SSE metadata](/learn/sdks/deep-dives/sse-metadata) (event ID, event type, retry) and [automatic reconnection](/learn/sdks/deep-dives/sse-metadata#automatic-reconnection) for resumable endpoints. [Learn more](/learn/sdks/deep-dives/sse-metadata)
- **Testing**: Auto-generated and handwritten tests for your SDK. [Learn more](/sdks/deep-dives/testing)
- **Code snippets**: No longer depend on manually written code snippets. [Learn more](/docs/api-references/sdk-snippets)
- **Augment with custom code**: Extend the generated SDK with additional functionality. [Learn more](/sdks/overview/custom-code)
diff --git a/fern/products/sdks/deep-dives/sse-metadata.mdx b/fern/products/sdks/deep-dives/sse-metadata.mdx
index 480e12584..07007044e 100644
--- a/fern/products/sdks/deep-dives/sse-metadata.mdx
+++ b/fern/products/sdks/deep-dives/sse-metadata.mdx
@@ -51,3 +51,50 @@ Each event exposes the parsed data alongside its protocol fields. Default iterat
## Stream resumption
The event ID is useful for resuming a stream via the standard `Last-Event-ID` header: store the last received ID as you iterate, then pass it back to the server on reconnection. This requires server-side support for the `Last-Event-ID` header.
+
+## Automatic reconnection
+
+Mark an SSE endpoint [`resumable`](/learn/api-definitions/openapi/endpoints/sse#resumable-streams) in your API definition (`x-fern-streaming.resumable: true` in OpenAPI, or `response-stream.resumable: true` in a Fern Definition) to have the SDK handle resumption for you. On a mid-stream drop, the SDK reconnects transparently, resending the last dispatched event ID in the `Last-Event-ID` header so iteration continues without gaps. No manual event-ID tracking is required.
+
+Reconnection honors the server's `retry:` directive for the reconnect delay, falling back to a 1-second default and capped at 30 seconds. The SDK retries up to 5 consecutive times by default; the counter resets whenever an event is received. Configure a [terminator](/learn/api-definitions/openapi/endpoints/sse#terminator-message) on the endpoint so the SDK can tell a completed stream from a dropped connection.
+
+Both the attempt cap and an on/off toggle are configurable per client and per request:
+
+
+
+ ```ts {2}
+ const stream = await client.plants.stream({ query: "fern" }, {
+ stream: { reconnectionEnabled: true, maxReconnectionAttempts: 3 }
+ });
+ ```
+
+
+ ```python {3-4}
+ stream = client.plants.stream(
+ query="fern",
+ stream_reconnection_enabled=True,
+ max_stream_reconnection_attempts=3,
+ )
+ ```
+
+
+ ```go {4}
+ stream := client.Plants.Stream(
+ ctx,
+ &PlantRequest{Query: "fern"},
+ option.WithMaxStreamReconnectAttempts(3), // or option.WithoutStreamReconnection()
+ )
+ ```
+
+
+ ```csharp {2}
+ var stream = await client.Plants.StreamAsync(new PlantRequest { Query = "fern" }, new RequestOptions {
+ MaxStreamReconnectAttempts = 3 // set DisableStreamReconnection = true to turn off
+ });
+ ```
+
+
+
+
+Automatic reconnection requires TypeScript SDK generator version 3.77.0+, Python 5.15.0+, Go 1.42.0+, or C# 2.71.0+.
+