HttpApiSchema
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.
Constructors
Signature
declare function Empty(code: number): Void;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"]>;
};StreamUint8Array
Creates a streaming Uint8Array success response schema.
Signature
declare const StreamUint8Array: (options?: { readonly contentType?: string }) => StreamUint8Array;withHeaders
Constructs a WithHeaders response value from a body and headers.
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>;WithHeaders
Wraps a success schema with a response headers schema.
Headers accept either a schema or a fields shorthand, mirroring the request-side headers option.
```ts import.meta.vitest import { Schema } from "effect" import { HttpApiSchema } from "effect/unstable/httpapi"
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 } ```
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>;Encoding
asFormUrlEncoded
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"];Marks a schema as a JSON payload / response.
Signature
declare function asJson(options?: {
readonly contentType?: string;
}): <S extends Top>(self: S) => S["Rebuild"];asMultipart
Signature
declare function asMultipart(options?: Options): <S extends Top>(self: S) => asMultipart<S>;asMultipartStream
Signature
declare function asMultipartStream(
options?: Options,
): <S extends Top>(self: S) => asMultipartStream<S>;asNoContent
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
Signature
declare function asNoContent<S extends Constraint>(options: {
readonly decode: LazyArg<S["Type"]>;
}): (self: S) => asNoContent<S>;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"];asUint8Array
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"];encodeToWithHeaders
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.
```ts import.meta.vitest import { Schema } from "effect" import { HttpApiSchema } from "effect/unstable/httpapi"
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 } } ```
See
WithHeadersfor 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>;Models
Type of the Accepted schema, a void schema annotated with HTTP status code 202.
Signature
interface Accepted extends Void {
constructor(_: never);
}Type of the Created schema, a void schema annotated with HTTP status code 201.
Signature
interface Created extends Void {
constructor(_: never);
}HTTP API body encoding metadata used by payloads and responses.
Signature
type Encoding = PayloadEncoding | ResponseEncoding;Type of the NoContent schema, a void schema annotated with HTTP status code 204.
Signature
interface NoContent extends Void {
constructor(_: never);
}PayloadEncoding type
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
HTTP API response body encoding metadata.
Signature
type ResponseEncoding = {
readonly _tag: "Json" | "FormUrlEncoded" | "Uint8Array" | "Text";
readonly contentType: string;
};SseEventFromData interface
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 | undefined;
},
{
readonly data: string;
readonly event?: string;
readonly id?: string;
},
Data["DecodingServices"],
Data["EncodingServices"]
> {}StatusLiteral type
Common HTTP status code literals accepted by status.
Signature
type StatusLiteral = keyof typeof statusCodeByLiteral;StreamSchema type
Schema for a streaming HTTP API success response.
Signature
type StreamSchema = StreamSse<Sse.EventCodec, Schema.Top, unknown> | StreamUint8Array;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/httpapi/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/httpapi/HttpApiSchema/Stream": "~effect/httpapi/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
Mode describing whether an SSE stream emits full events or raw data values.
Signature
type StreamSseMode = "events" | "data";StreamUint8Array interface
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/httpapi/HttpApiSchema/Stream": "~effect/httpapi/HttpApiSchema/Stream";
readonly contentType: string;
readonly mode: "uint8array";
readonly Rebuild: StreamUint8Array;
}withHeaders interface
The Type of a WithHeaders schema: what handlers return and what the client resolves to, constructed via withHeaders.
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/httpapi/HttpApiSchema/WithHeadersValue": "~effect/httpapi/HttpApiSchema/WithHeadersValue";
readonly body: A;
readonly headers: H;
}WithHeaders interface
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/httpapi/HttpApiSchema/WithHeaders": "~effect/httpapi/HttpApiSchema/WithHeaders";
readonly headers: H;
readonly Rebuild: WithHeaders<S, H>;
readonly schema: S;
}Predicates
isNoContent
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;isWithHeaders
Returns true when a schema is a WithHeaders response schema.
```ts import.meta.vitest import { Schema } from "effect" import { HttpApiSchema } from "effect/unstable/httpapi"
const schema = HttpApiSchema.WithHeaders(Schema.String, { "x-request-id": Schema.String })
HttpApiSchema.isWithHeaders(schema) // => true HttpApiSchema.isWithHeaders(Schema.String) // => false ```
Signature
declare function isWithHeaders(u: unknown): u is WithHeaders<Top, Top>;Schemas
Schema for empty HTTP responses with status code 202.
Signature
declare const Accepted: Accepted;asMultipart interface
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
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
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);
}Schema for empty HTTP responses with status code 201.
Signature
declare const Created: Created;encodeToWithHeaders interface
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);
}Schema for empty HTTP responses with status code 204.
Signature
declare const NoContent: NoContent;Sets the HTTP status code of a schema.
Details
This is equivalent to calling .annotate({ httpApiStatus: code }) on the schema. You can pass either a numeric status code (for example, 201) or a common literal name (for example, "Created").
Signature
declare function status(code: number): <S extends Top>(self: S) => S["Rebuild"];
declare function status(
code:
| "NotFound"
| "Forbidden"
| "Unauthorized"
| "InternalServerError"
| "Continue"
| "BadRequest"
| "MethodNotAllowed"
| "NotAcceptable"
| "RequestTimeout"
| "Conflict"
| "Gone"
| "UnprocessableEntity"
| "NotImplemented"
| "ServiceUnavailable"
| "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"];Type IDs
MultipartStreamTypeId
Runtime brand key used to mark schemas as streaming multipart payloads.
Signature
declare const MultipartStreamTypeId: "~effect/httpapi/HttpApiSchema/MultipartStream";MultipartStreamTypeId type
Type-level brand identifier used by asMultipartStream.
Signature
type MultipartStreamTypeId = typeof MultipartStreamTypeId;MultipartTypeId
Runtime brand key used to mark schemas as buffered multipart payloads.
Signature
declare const MultipartTypeId: "~effect/httpapi/HttpApiSchema/Multipart";MultipartTypeId type
Type-level brand identifier used by asMultipart.
Signature
type MultipartTypeId = typeof MultipartTypeId;WithHeadersTypeId
Runtime brand key used to mark WithHeaders response schemas.
Signature
declare const WithHeadersTypeId: "~effect/httpapi/HttpApiSchema/WithHeaders";WithHeadersTypeId type
Type-level brand identifier used by WithHeaders.
Signature
type WithHeadersTypeId = typeof WithHeadersTypeId;WithHeadersValueTypeId
Runtime brand key used to mark WithHeaders response values.
Signature
declare const WithHeadersValueTypeId: "~effect/httpapi/HttpApiSchema/WithHeadersValue";WithHeadersValueTypeId type
Type-level brand identifier used by WithHeaders response values.
Signature
type WithHeadersValueTypeId = typeof WithHeadersValueTypeId;
Creates a void schema with the given HTTP status code. This is used to represent empty responses with a specific status code.
See
NoContentfor the predefined 204 no content schema.