Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

HttpApiSchema unstable

Attaches HTTP API metadata to Effect Schema values.

This module is the schema-side bridge for HttpApi endpoint builders, generated clients, and OpenAPI support. It does not define routes or perform IO. Instead, the helpers annotate schemas so the surrounding HTTP API tooling can choose response status codes, content types, body codecs, multipart handling, and no-body response behavior.

45 exports Since v4.0.0 Source

Constructors

Empty

unstable
Since v4.0.0

Creates a void schema with the given HTTP status code. This is used to represent empty responses with a specific status code.

See

  • NoContent for the predefined 204 no content schema.

Signature

declare function Empty(code: number): Void

StreamSse

unstable
Since v4.0.0

Creates a Server-Sent Events streaming success response schema.

Signature

declare const StreamSse: {
<Events extends EventCodec, Error extends Constraint = Never>(options: {
readonly contentType?: string;
readonly error?: Error;
readonly events: Events;
}): StreamSse<Events, Error, Events["Type"]>;
<Data extends Constraint, Error extends Constraint = Never>(options: {
readonly contentType?: string;
readonly data: Data;
readonly error?: Error;
}): StreamSse<SseEventFromData<Data>, Error, Data["Type"]>;
}
Since v4.0.0

Creates a streaming Uint8Array success response schema.

Signature

declare const StreamUint8Array: (options?: {
readonly contentType?: string;
}) => StreamUint8Array

withHeaders

unstable
Since v4.0.0

Constructs a WithHeaders response value from a body and headers.

Details

The returned value is branded so servers and clients can detect it exactly, including in mixed success unions. The same shape is used on both sides: a value received from a client can be returned from another handler unchanged.

See WithHeaders for an example that constructs a schema and its corresponding response value.

Signature

declare const withHeaders: <A, H>(options: {
readonly body: A;
readonly headers: H;
}) => withHeaders<A, H>

Encoding

Since v4.0.0

Marks a schema as an application/x-www-form-urlencoded payload or response.

Details

The schema's encoded side must be a record of strings.

Signature

declare function asFormUrlEncoded(options?: {
readonly contentType?: string;
}): <S extends Top>(self: S) => S["Rebuild"]

asJson

unstable
Since v4.0.0

Marks a schema as a JSON payload / response.

Signature

declare function asJson(options?: {
readonly contentType?: string;
}): <S extends Top>(self: S) => S["Rebuild"]

asMultipart

unstable
Since v4.0.0

Marks a schema as a multipart payload.

See

Signature

declare function asMultipart(options?: Options): <S extends Top>(self: S) => asMultipart<S>
Since v4.0.0

Marks a schema as a multipart stream payload.

See

Signature

declare function asMultipartStream(options?: Options): <S extends Top>(self: S) => asMultipartStream<S>

asNoContent

unstable
Since v4.0.0

Marks a schema as a no-content response while preserving a decoded client value.

Details

The server encodes the response as void; generated clients call decode to produce the schema's decoded value when the response has no body.

See

  • NoContent for a void schema with the status code 204.
  • Empty for creating a void schema with a specific status code.

Signature

declare function asNoContent<S extends Constraint>(options: {
readonly decode: LazyArg<S["Type"]>;
}): (self: S) => asNoContent<S>

asText

unstable
Since v4.0.0

Marks a schema as a text payload / response.

Details

The schema encoded side must be a string.

Signature

declare function asText(options?: {
readonly contentType?: string;
}): <S extends Top & {
readonly Encoded: string;
}>(self: S) => S["Rebuild"]
Since v4.0.0

Marks a schema as a binary payload / response.

Details

The schema encoded side must be a Uint8Array.

Signature

declare function asUint8Array(options?: {
readonly contentType?: string;
}): <S extends Top & {
readonly Encoded: Uint8Array;
}>(self: S) => S["Rebuild"]
Since v4.0.0

Encodes a schema as a { body, headers } pair, folding response headers into an opaque domain type such as an error class.

Details

The encoded side is the pair of the body schema and the headers fields; the Type stays the source schema's Type. The body schema is authoritative for everything wire-level: status, content type, and response encoding resolve from the body schema's annotations.

The mappings are pure total functions: validation lives in the body and header schemas, the mappings only reshape valid data.

Streams used as the body schema turn mid-stream transport errors into defects on the client. Stream responses should use WithHeaders, which preserves the body stream's error channel in the generated client.

See

  • WithHeaders for the structural wrapper recommended for success responses, including streams.

Signature

declare function encodeToWithHeaders<S extends Top, Body extends Top, Headers extends Fields>(options: {
readonly body: Body;
readonly headers: Headers;
}, transformation: {
readonly decode: (value: View<{
readonly body: Body;
readonly headers: Struct<Headers>;
}>) => S["Type"];
readonly encode: (value: S["Type"]) => View<{
readonly body: Body;
readonly headers: Struct<Headers>;
}>;
}): (self: S) => encodeToWithHeaders<S, Body, Headers>

Example Encoding an error with headers

import { Schema } from "effect"
import { HttpApiSchema } from "effect/http-api"
class UserNotFound extends Schema.TaggedError<UserNotFound>()("UserNotFound", {
userId: Schema.Int
}) {}
const UserNotFoundWithHeaders = UserNotFound.pipe(
HttpApiSchema.encodeToWithHeaders({
body: HttpApiSchema.Empty(404),
headers: {
"x-user-id": Schema.Int
}
}, {
decode: ({ headers }) => new UserNotFound({ userId: headers["x-user-id"] }),
encode: (error) => ({
headers: { "x-user-id": error.userId },
body: undefined
})
})
)
const encoded = Schema.encodeSync(UserNotFoundWithHeaders)(new UserNotFound({ userId: 123 }))
encoded // => { body: undefined, headers: { "x-user-id": 123 } }

Models

Accepted

interface unstable
Since v4.0.0

Type of the Accepted schema, a void schema annotated with HTTP status code 202.

Signature

interface Accepted extends Void {
constructor(_: never);
}

Created

interface unstable
Since v4.0.0

Type of the Created schema, a void schema annotated with HTTP status code 201.

Signature

interface Created extends Void {
constructor(_: never);
}

Encoding

type unstable
Since v4.0.0

HTTP API body encoding metadata used by payloads and responses.

Signature

type Encoding = PayloadEncoding | ResponseEncoding

NoContent

interface unstable
Since v4.0.0

Type of the NoContent schema, a void schema annotated with HTTP status code 204.

Signature

interface NoContent extends Void {
constructor(_: never);
}

PayloadEncoding

type unstable
Since v4.0.0

HTTP API request payload encoding metadata.

Signature

type PayloadEncoding = {
readonly _tag: "Multipart";
readonly contentType: string;
readonly limits?: Multipart_.withLimits.Options;
readonly mode: "buffered" | "stream";
} | {
readonly _tag: "Json" | "FormUrlEncoded" | "Uint8Array" | "Text";
readonly contentType: string;
}

ResponseEncoding

type unstable
Since v4.0.0

HTTP API response body encoding metadata.

Signature

type ResponseEncoding = {
readonly _tag: "Json" | "FormUrlEncoded" | "Uint8Array" | "Text";
readonly contentType: string;
}

SseEventFromData

interface unstable
Since v4.0.0

Event schema produced when StreamSse is constructed from a JSON data schema.

Signature

interface SseEventFromData<Data extends Schema.Constraint> extends ConstraintCodec<{
readonly data: Data["Type"];
readonly event: string;
readonly id?: string;
}, {
readonly data: string;
readonly event?: string;
readonly id?: string;
}, Data["DecodingServices"], Data["EncodingServices"]> {}

StatusLiteral

type unstable
Since v4.0.0

Common HTTP status code literals accepted by status.

Signature

type StatusLiteral = HttpStatus.Literal

StreamSchema

type unstable
Since v4.0.0

Schema for a streaming HTTP API success response.

Signature

type StreamSchema = StreamSse<Sse.EventCodec, Schema.Top, unknown> | StreamUint8Array

StreamSse

interface unstable
Since v4.0.0

Schema for a Server-Sent Events success response.

Details

events describes successful application events emitted by the stream, and error describes typed stream failures that will be encoded by later endpoint/server/client integrations using the reserved failure event. If error is omitted, it defaults to Schema.Never. When StreamSse is constructed from data, handlers and clients expose raw data values while the server and client still use an SSE event schema internally.

Gotchas

The client treats effect/http-api/stream/failure as a stream failure only when its decoded data is a Cause. If an event schema accepts that name dynamically but decodes data to another value, the client emits it as an application event. Endpoint construction rejects event schemas that declare the reserved name statically.

Signature

interface StreamSse<Events extends Sse.EventCodec, Error extends Schema.Constraint, Value = Events["Type"]> extends BottomLazy<SchemaAST.Declaration, StreamSse<Events, Error, Value>> {
constructor(_: never);
readonly _tag: "StreamSse";
readonly "~effect/http-api/HttpApiSchema/Stream": "~effect/http-api/HttpApiSchema/Stream";
readonly "~type.make": Stream<Value, Error["Type"], never>;
readonly "~type.make.in": Stream<Value, Error["Type"], never>;
readonly "~Value"?: Value;
readonly contentType: string;
readonly DecodingServices: Events["DecodingServices"] | Error["DecodingServices"];
readonly Encoded: Stream<Value, Error["Type"], never>;
readonly EncodingServices: Events["EncodingServices"] | Error["EncodingServices"];
readonly error: Error;
readonly events: Events;
readonly Iso: Stream<Value, Error["Type"], never>;
readonly mode: "sse";
readonly Rebuild: StreamSse<Events, Error, Value>;
readonly sseMode: StreamSseMode;
readonly Type: Stream<Value, Error["Type"], never>;
}

StreamSseMode

type unstable
Since v4.0.0

Mode describing whether an SSE stream emits full events or raw data values.

Signature

type StreamSseMode = "events" | "data"

StreamUint8Array

interface unstable
Since v4.0.0

Schema for a streaming Uint8Array success response.

Details

This declaration stores the response content type for later endpoint, server, client, and OpenAPI integrations. It is intentionally separate from the buffered asUint8Array response encoding.

Signature

interface StreamUint8Array extends Bottom<Stream.Stream<Uint8Array, unknown, never>, Stream.Stream<Uint8Array, unknown, never>, never, never, SchemaAST.Declaration, StreamUint8Array> {
constructor(_: never);
readonly _tag: "StreamUint8Array";
readonly "~effect/http-api/HttpApiSchema/Stream": "~effect/http-api/HttpApiSchema/Stream";
readonly contentType: string;
readonly mode: "uint8array";
readonly Rebuild: StreamUint8Array;
}

withHeaders

interface unstable
Since v4.0.0

The Type of a WithHeaders schema: what handlers return and what the client resolves to, constructed via withHeaders.

Details

body is the inner success value. For stream success schemas it is the Stream itself, so headers are decided before the body starts streaming.

Signature

interface withHeaders<A, H> {
readonly "~effect/http-api/HttpApiSchema/WithHeadersValue": "~effect/http-api/HttpApiSchema/WithHeadersValue";
readonly body: A;
readonly headers: H;
}

WithHeaders

interface unstable
Since v4.0.0

A response schema wrapping a body schema together with a response headers schema.

Details

WithHeaders is a branded declaration schema: it carries the inner success schema and the headers schema as properties, and server, client, and OpenAPI integrations detect the brand and handle body and headers separately. It is supported for error responses, though encodeToWithHeaders is usually more convenient there because handlers can fail with the domain error value.

  • schema is the inner response schema. Success responses may wrap StreamSse and StreamUint8Array; error responses remain non-streaming. Nesting WithHeaders is rejected at construction.
  • headers is any schema; endpoint construction applies Schema.toCodecStringTree unless codecs are disabled, so leaves become string | undefined on the wire and undefined leaves are omitted from the response.
  • Status and response-encoding annotations are resolved from the wrapper first, falling through to the inner schema.
  • A header-carrying response cannot share its status and content type with another response in the same success or error union. Endpoint construction rejects ambiguous declarations, including those made with encodeToWithHeaders.
  • Rebuild preserves the brand and both parts, so .annotate keeps the wrapper intact.

Signature

interface WithHeaders<S extends Schema.Top, H extends Schema.Top> extends Bottom<withHeaders<S["Type"], H["Type"]>, withHeaders<S["Encoded"], Schema.StringTree>, S["DecodingServices"] | H["DecodingServices"], S["EncodingServices"] | H["EncodingServices"], SchemaAST.Declaration, WithHeaders<S, H>> {
constructor(_: never);
readonly "~effect/http-api/HttpApiSchema/WithHeaders": "~effect/http-api/HttpApiSchema/WithHeaders";
readonly headers: H;
readonly Rebuild: WithHeaders<S, H>;
readonly schema: S;
}

Other

Signature

declare function status(code: number): <S extends Top>(self: S) => S["Rebuild"]
declare function status(code: "NotFound" | "Forbidden" | "Unauthorized" | "InternalServerError" | "BadRequest" | "MethodNotAllowed" | "NotAcceptable" | "RequestTimeout" | "Conflict" | "Gone" | "UnprocessableEntity" | "NotImplemented" | "ServiceUnavailable" | "Continue" | "SwitchingProtocols" | "Processing" | "EarlyHints" | "OK" | "Ok" | "Created" | "Accepted" | "NonAuthoritativeInformation" | "NoContent" | "ResetContent" | "PartialContent" | "MultiStatus" | "AlreadyReported" | "ImUsed" | "MultipleChoices" | "MovedPermanently" | "Found" | "SeeOther" | "NotModified" | "TemporaryRedirect" | "PermanentRedirect" | "PaymentRequired" | "ProxyAuthenticationRequired" | "LengthRequired" | "PreconditionFailed" | "PayloadTooLarge" | "UriTooLong" | "UnsupportedMediaType" | "RangeNotSatisfiable" | "ExpectationFailed" | "ImATeapot" | "MisdirectedRequest" | "Locked" | "FailedDependency" | "TooEarly" | "UpgradeRequired" | "PreconditionRequired" | "TooManyRequests" | "RequestHeaderFieldsTooLarge" | "UnavailableForLegalReasons" | "BadGateway" | "GatewayTimeout" | "HttpVersionNotSupported" | "VariantAlsoNegotiates" | "InsufficientStorage" | "LoopDetected" | "NotExtended" | "NetworkAuthenticationRequired"): <S extends Top>(self: S) => S["Rebuild"]

Signature

declare function WithHeaders<S extends Top, H extends Fields>(schema: S, headers: H): WithHeaders<S, Struct<H>>
declare function WithHeaders<S extends Top, H extends Top>(schema: S, headers: H): WithHeaders<S, H>

Example Adding response headers to a success schema

import { Schema } from "effect"
import { HttpApiSchema } from "effect/http-api"
const schema = HttpApiSchema.WithHeaders(Schema.String, {
"x-total-count": Schema.FiniteFromString
})
const response: typeof schema.Type = HttpApiSchema.withHeaders({
body: "created",
headers: { "x-total-count": 1 }
})
HttpApiSchema.isWithHeaders(schema) // => true
response.body // => "created"
response.headers // => { "x-total-count": 1 }

Predicates

isNoContent

unstable
Since v4.0.0

Returns true when a schema AST represents a no-content response.

Details

The check succeeds for direct void schemas and schemas whose encoded or transformation target is void.

Signature

declare function isNoContent(ast: AST): boolean
Since v4.0.0

Returns true when a schema is a WithHeaders response schema.

Signature

declare function isWithHeaders(u: unknown): u is WithHeaders<Top, Top>

Example Detecting a response headers schema

import { Schema } from "effect"
import { HttpApiSchema } from "effect/http-api"
const schema = HttpApiSchema.WithHeaders(Schema.String, {
"x-request-id": Schema.String
})
HttpApiSchema.isWithHeaders(schema) // => true
HttpApiSchema.isWithHeaders(Schema.String) // => false

Schemas

Accepted

unstable
Since v4.0.0

Schema for empty HTTP responses with status code 202.

Signature

declare const Accepted: Accepted

asMultipart

interface unstable
Since v4.0.0

Schema type returned by asMultipart for buffered multipart payloads.

Signature

interface asMultipart<S extends Schema.Top> extends brand<S["Rebuild"], MultipartTypeId> {
constructor(_: never);
}

asMultipartStream

interface unstable
Since v4.0.0

Schema type returned by asMultipartStream for streaming multipart payloads.

Signature

interface asMultipartStream<S extends Schema.Top> extends brand<S["Rebuild"], MultipartStreamTypeId> {
constructor(_: never);
}

asNoContent

interface unstable
Since v4.0.0

Schema type returned by asNoContent, encoding as void while decoding to the original schema type.

Signature

interface asNoContent<S extends Schema.Constraint> extends decodeTo<Schema.toType<S>, Schema.Void> {
constructor(_: never);
}

Created

unstable
Since v4.0.0

Schema for empty HTTP responses with status code 201.

Signature

declare const Created: Created

encodeToWithHeaders

interface unstable
Since v4.0.0

Schema type returned by encodeToWithHeaders, encoding as a { body, headers } pair while decoding to the source schema type.

Signature

interface encodeToWithHeaders<S extends Schema.Top, Body extends Schema.Top, Headers extends Schema.Struct.Fields> extends decodeTo<Schema.toType<S>, Schema.Struct<{
readonly body: Body;
readonly headers: Schema.Struct<Headers>;
}>> {
constructor(_: never);
}

NoContent

unstable
Since v4.0.0

Schema for empty HTTP responses with status code 204.

Signature

declare const NoContent: NoContent

Type IDs

Since v4.0.0

Runtime brand key used to mark schemas as streaming multipart payloads.

Signature

declare const MultipartStreamTypeId: "~effect/http-api/HttpApiSchema/MultipartStream"
Since v4.0.0

Type-level brand identifier used by asMultipartStream.

Signature

type MultipartStreamTypeId = typeof MultipartStreamTypeId
Since v4.0.0

Runtime brand key used to mark schemas as buffered multipart payloads.

Signature

declare const MultipartTypeId: "~effect/http-api/HttpApiSchema/Multipart"

MultipartTypeId

type unstable
Since v4.0.0

Type-level brand identifier used by asMultipart.

Signature

type MultipartTypeId = typeof MultipartTypeId
Since v4.0.0

Runtime brand key used to mark WithHeaders response schemas.

Signature

declare const WithHeadersTypeId: "~effect/http-api/HttpApiSchema/WithHeaders"

WithHeadersTypeId

type unstable
Since v4.0.0

Type-level brand identifier used by WithHeaders.

Signature

type WithHeadersTypeId = typeof WithHeadersTypeId

Runtime brand key used to mark WithHeaders response values.

Signature

declare const WithHeadersValueTypeId: "~effect/http-api/HttpApiSchema/WithHeadersValue"
Since v4.0.0

Type-level brand identifier used by WithHeaders response values.

Signature

type WithHeadersValueTypeId = typeof WithHeadersValueTypeId