> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://buildwithfern.com/learn/llms.txt. # Server-sent events and streaming APIs The `x-fern-streaming` extension allows you to represent endpoints that are streaming. ## JSON streaming If your API returns a series of newline-delimited `JSON` chunks, under `application/json`, `application/x-ndjson`, or any other `*json` content type, as seen below ```json { "text": "Hi, I am a" } { "text": "chatbot. Do you have any"} { "text": "questions for me"} ``` then add `x-fern-streaming: true` to your OpenAPI operation. The boolean shorthand selects JSON streaming, and the generated SDKs expose the endpoint as an async-iterable stream that splits the response on newlines and parses each line as JSON. Fern auto-detects streaming only for `text/event-stream` responses, so a JSON stream content type such as `application/x-ndjson` still requires the extension. **`openapi.yml`** ```yaml title="openapi.yml" {4} paths: /logs: post: x-fern-streaming: true responses: "200": content: application/json: schema: $ref: "#/components/schemas/Chat" components: schemas: Chat: type: object properties: text: type: string ``` ## Server-sent events #### Enterprise feature for SDKs Using this feature in generated SDKs requires the [Enterprise plan](https://buildwithfern.com/pricing). To get started, reach out to [support@buildwithfern.com](mailto:support@buildwithfern.com). If your API returns server-sent-events (SSE), with the `data` and `event` keys as seen below ```json data: { "text": "Hi, I am a" } data: { "text": "chatbot. Do you have any"} data: { "text": "questions for me"} ``` then include `format: sse`. **`openapi.yml`** ```yaml title="openapi.yml" {4-5} paths: /logs: post: x-fern-streaming: format: sse responses: "200": content: application/json: schema: $ref: "#/components/schemas/Chat" components: schemas: Chat: type: object properties: text: type: string ``` Generated SDKs expose each event's [metadata — event ID, event type, and retry interval](/learn/sdks/deep-dives/sse-metadata) to your end users. If your SSE endpoint uses the `event` field to discriminate between different event types in a `oneOf`, Fern auto-infers that the discriminator is at the protocol level. Use [`x-fern-discriminator-context`](/learn/api-definitions/openapi/extensions/discriminator-context) to override the inferred value when needed. ### Terminator message Some SSE APIs send a standalone terminator message to signal that the stream is complete. For example, OpenAI's API sends `[DONE]` as a final message. You can specify this with the `terminator` field: **`openapi.yml`** ```yaml title="openapi.yml" {4-6} paths: /logs: post: x-fern-streaming: format: sse terminator: "[DONE]" # ... 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. **`openapi.yml`** ```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: **`openapi.yml`** ```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 controls whether the response is streamed or not. Fern supports this pattern in a first class way. Specify the `stream-condition` alongside the ordinary response and the streaming response: **`openapi.yml`** ```yaml title="openapi.yml" {4-11} paths: /logs: post: x-fern-streaming: format: sse terminator: "[DONE]" stream-condition: $request.stream response: $ref: '#/components/schemas/Chat' response-stream: $ref: '#/components/schemas/ChatChunk' components: schemas: Chat: type: object properties: text: type: string tokens: type: number ChatChunk: type: object properties: text: type: string ``` > Use the `x-fern-streaming` extension to model streaming endpoints