Skip to content

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.

45 exports Added in v4.0.0 Source

Constructors

Empty

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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"]>;
};

Creates a streaming Uint8Array success response schema.

Signature

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

withHeaders

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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

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

Added in v4.0.0 Source

Marks a schema as a JSON payload / response.

Signature

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

asMultipart

Added in v4.0.0 Source

Marks a schema as a multipart payload.

See

Signature

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

Marks a schema as a multipart stream payload.

See

Signature

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

asNoContent

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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"];

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

  • 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>;

Models

Accepted interface

Added in v4.0.0 Source

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

Signature

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

Created interface

Added in v4.0.0 Source

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

Signature

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

Encoding type

Added in v4.0.0 Source

HTTP API body encoding metadata used by payloads and responses.

Signature

type Encoding = PayloadEncoding | ResponseEncoding;

NoContent interface

Added in v4.0.0 Source

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

Signature

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

PayloadEncoding type

Added in v4.0.0 Source

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

Added in v4.0.0 Source

HTTP API response body encoding metadata.

Signature

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

SseEventFromData interface

Added in v4.0.0 Source

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

Added in v4.0.0 Source

Common HTTP status code literals accepted by status.

Signature

type StatusLiteral = keyof typeof statusCodeByLiteral;

StreamSchema type

Added in v4.0.0 Source

Schema for a streaming HTTP API success response.

Signature

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

StreamSse interface

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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

Signature

type StreamSseMode = "events" | "data";

StreamUint8Array interface

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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;

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

Accepted

Added in v4.0.0 Source

Schema for empty HTTP responses with status code 202.

Signature

declare const Accepted: Accepted;

asMultipart interface

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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

Added in v4.0.0 Source

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

Added in v4.0.0 Source

Schema for empty HTTP responses with status code 201.

Signature

declare const Created: Created;

encodeToWithHeaders interface

Added in v4.0.0 Source

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

Added in v4.0.0 Source

Schema for empty HTTP responses with status code 204.

Signature

declare const NoContent: NoContent;

status

Added in v4.0.0 Source

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

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

Signature

declare const MultipartStreamTypeId: "~effect/httpapi/HttpApiSchema/MultipartStream";

Type-level brand identifier used by asMultipartStream.

Signature

type MultipartStreamTypeId = typeof MultipartStreamTypeId;

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

Signature

declare const MultipartTypeId: "~effect/httpapi/HttpApiSchema/Multipart";

MultipartTypeId type

Added in v4.0.0 Source

Type-level brand identifier used by asMultipart.

Signature

type MultipartTypeId = typeof MultipartTypeId;

Runtime brand key used to mark WithHeaders response schemas.

Signature

declare const WithHeadersTypeId: "~effect/httpapi/HttpApiSchema/WithHeaders";

WithHeadersTypeId type

Added in v4.0.0 Source

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/httpapi/HttpApiSchema/WithHeadersValue";

Type-level brand identifier used by WithHeaders response values.

Signature

type WithHeadersValueTypeId = typeof WithHeadersValueTypeId;