Skip to navigation

Server-sent events and streaming APIs

Use the x-fern-streaming extension to model streaming endpoints

View as Markdown

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

{ "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
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. To get started, reach out to support@buildwithfern.com.

If your API returns server-sent-events (SSE), with the data and event keys as seen below

data: { "text": "Hi, I am a" }
data: { "text": "chatbot. Do you have any"}
data: { "text": "questions for me"}

then include format: sse.

openapi.yml
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 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 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
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. 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
paths:
/logs:
post:
x-fern-streaming:
format: sse
terminator: "[DONE]"
resumable: true
# ... responses and schemas

Configure a terminator 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
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
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