OpenAPI Server for Delphi

TsgcOpenAPIServer publishes a live OpenAPI 3.x document, routes incoming requests against the spec, validates payloads in both directions, and ships an embedded Swagger UI and Redoc — all from a single Delphi component on top of the sgcWebSockets HTTP/2 server.

OpenAPI 3.0 & 3.1
HTTP/2 + TLS 1.3
Swagger UI + Redoc
Spec-first or Code-first

TsgcOpenAPIServer

A single Delphi component that turns an OpenAPI specification into a running, validated, self-documenting HTTP/2 server.

Component class

TsgcOpenAPIServer

Transport

HTTP/1.1, HTTP/2, WebSocket upgrade, TLS via OpenSSL or SChannel

Spec formats

OpenAPI 3.0, OpenAPI 3.1, Swagger 2.0 (auto-converted)

Platforms

Windows, Linux, macOS — Delphi 7 to 13, C++Builder, FPC

Edition

Standard / Professional / Enterprise — all include the server

Built on

sgcWebSockets HTTP server (same TLS, HTTP/2, auth and logging pipeline)

Spec-first or Code-first — You Choose

The same component runs in either mode. Start from a YAML/JSON contract, or describe the API in Delphi and let the component publish the spec for you.

1. Spec-first

Load openapi.yaml, bind handlers to operation IDs, and start serving. Routes, parameter binding, content negotiation and validation come straight from the contract — you only write the business logic.

Best for: teams with a shared design contract, API-led integration, or polyglot back-ends where the spec is the source of truth.

2. Code-first

Register handlers in Pascal with annotations (path, verb, request schema, response schema, security). The component builds the OpenAPI document at runtime and exposes it on /openapi.json.

Best for: rapid prototyping, internal services, or porting an existing TIdHTTPServer / DataSnap REST surface to a self-documenting API.

A Working Server in 20 Lines

Drop the component on a form, point it at an OpenAPI document, bind one operation, hit Run. That is the entire setup.

Delphi
uses
  sgcOpenAPI_Server, sgcOpenAPI_Types, sgcHTTP_Server;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FServer := TsgcOpenAPIServer.Create(nil);
  FServer.HTTPServer := sgcHTTPServer1;        // reuse the sgcWebSockets HTTP/2 server
  FServer.Spec.LoadFromFile('petstore.yaml');  // any OpenAPI 3.x doc
  FServer.PublishSpecPath := '/openapi.json';
  FServer.SwaggerUIPath   := '/docs';
  FServer.RedocPath       := '/redoc';

  // Bind one operation defined in the spec (operationId = "getPetById")
  FServer.OnOperation_getPetById :=
    procedure(const Ctx: TsgcOpenAPIContext)
    var
      oPet: TJSONObject;
    begin
      oPet := TJSONObject.Create;
      oPet.AddPair('id',     Ctx.PathParams['petId']);
      oPet.AddPair('name',   'Rex');
      oPet.AddPair('status', 'available');
      Ctx.RespondJSON(200, oPet);
    end;

  sgcHTTPServer1.Port   := 8080;
  sgcHTTPServer1.Active := True;
end;

What you get out of the box: GET /pets/{petId} serves the handler above, GET /openapi.json returns the live spec, GET /docs opens Swagger UI, GET /redoc opens Redoc — with HTTP/2 and TLS already on if sgcHTTPServer1 has them configured.

Parameters declared in the OpenAPI document are parsed, type-checked and exposed through a single typed context. Wrong types return 400 Bad Request before your handler runs.

Delphi
// spec snippet
//   /pets:
//     get:
//       operationId: listPets
//       parameters:
//         - name: limit       in: query    schema: { type: integer, maximum: 100 }
//         - name: status      in: query    schema: { type: string, enum: [available, pending, sold] }
//         - name: X-Tenant-Id in: header   required: true

FServer.OnOperation_listPets :=
  procedure(const Ctx: TsgcOpenAPIContext)
  var
    vLimit:  Integer;
    vStatus: string;
    vTenant: string;
  begin
    vLimit  := Ctx.QueryParamInt('limit', 20);     // default 20
    vStatus := Ctx.QueryParam   ('status', 'available');
    vTenant := Ctx.HeaderParam  ('X-Tenant-Id');   // required → validated

    Ctx.RespondJSON(200, PetRepo.List(vTenant, vStatus, vLimit));
  end;

Schema Validation in Both Directions

Every incoming body is validated against the operation's requestBody schema. Every response is validated against the declared status code. Mismatches return RFC 7807 problem-details with field-level diagnostics.

Request validation

Required fields, type coercion, enum membership, format validators (email, uuid, date-time, ipv4/6), minLength / maxLength, minimum / maximum, pattern, additionalProperties, oneOf / anyOf / allOf — all enforced before your handler runs.

Response validation

Optional in production, strict in development. Helps you catch the day your handler returns an extra field that's not in the contract before a downstream consumer breaks.

Custom validators

Hook into OnBeforeValidate to add domain rules (currency code is supported, SKU exists, tenant is active). Returns the same RFC 7807 envelope as built-in validators for uniform error UX.

JSON — sample 400 response
{
  "type":   "https://example.com/probs/validation",
  "title":  "Request body failed schema validation",
  "status": 400,
  "errors": [
    { "path": "/email",    "message": "not a valid email address" },
    { "path": "/age",      "message": "value 213 exceeds maximum 120" },
    { "path": "/status",   "message": "value 'archived' not in enum [active,pending]" }
  ]
}

Auth Schemes Wired Up From the Spec

Every securityScheme declared in the document is enforced automatically. You only write the credential lookup — the component does the parsing, the challenge headers, and the 401/403 responses.

API Key

Header, query or cookie. Multiple keys per operation. Constant-time comparison.

HTTP Basic / Bearer

RFC 7617 / RFC 6750 with realm support. Credentials never logged.

JWT (RS256 / ES256 / HS256)

JWKS auto-fetch and cache. Issuer, audience, expiration and custom-claim checks.

OAuth2

Authorization Code, Client Credentials, Password and Implicit flows. PKCE supported.

OpenID Connect

Discovery document loaded from /.well-known/openid-configuration. ID token validated against JWKS.

mTLS

Per-operation client-certificate enforcement. Common Name and SAN extraction available in the context.

Delphi — JWT validation hook
FServer.Security.JWT.JWKSUri := 'https://auth.example.com/.well-known/jwks.json';
FServer.Security.JWT.Audience := 'api.example.com';
FServer.Security.JWT.Issuer   := 'https://auth.example.com/';

FServer.OnAuthorize :=
  procedure(const Ctx: TsgcOpenAPIContext; var Allow: Boolean)
  begin
    // Token already verified. Apply business rule on a custom claim.
    Allow := Ctx.JWT.Claims['tenant'] = Ctx.PathParams['tenant'];
  end;

Swagger UI & Redoc Embedded

No external dependencies, no Node.js, no swagger-codegen in the deployment pipeline. Both UIs are bundled inside the component and serve straight from the spec at runtime.

/openapi.json & /openapi.yaml

The live document — always in sync with what the server actually serves. Point any client generator (sgcOpenAPI, openapi-generator, oapi-codegen) at this URL.

/docs — Swagger UI

The familiar interactive Swagger UI — try operations, browse schemas, see examples. Configurable theme, deepLinking, and OAuth2 redirect.

/redoc — Redoc

The clean, three-pane Redoc layout for static-feel API documentation. Same source, different presentation.

Content Negotiation Done Right

application/json

UTF-8, RFC 8259 strict. Numbers, booleans, nulls, nested objects and arrays.

application/yaml

YAML 1.2 with schema-aware parsing. Useful for human-edited request bodies.

application/x-www-form-urlencoded

Classic form posts — bound to the request schema like any other body.

multipart/form-data

File uploads with size limits, MIME-type allow lists, and per-part schema binding.

text/event-stream (SSE)

Long-running streamed responses — reuses the sgcWebSockets SSE writer.

application/octet-stream

Raw binary download / upload with byte-range request support.

One HTTP Server, Many Surfaces

TsgcOpenAPIServer plugs into the same sgcWebSockets HTTP/2 server that hosts your WebSocket endpoints, AI/LLM streams and static files. One port, one TLS certificate, one logging stream.

HTTP/2 multiplexing

Hundreds of REST operations and a long-lived WebSocket subscription share the same TLS connection. Browser clients get one round-trip handshake, you get fewer sockets to keep alive.

WebSocket promotion

Declare x-sgc-upgrade: websocket on a path and the component performs the RFC 6455 upgrade for you — the same operation does both REST and bi-directional streaming.

Static asset routes

Drop the SPA build under /app on the same component — clean URLs, gzip, brotli, ETag and HTTP/2 server-push for free.

Typical Deployments

Public REST APIs

Versioned, contract-tested, with auto-generated SDKs that your customers can download from /openapi.json.

Internal microservices

Service-to-service contracts that survive refactors — the spec is the integration test.

Industrial / IoT gateways

Edge devices exposing a documented REST control plane plus an MQTT or WebSocket telemetry surface from the same Delphi binary.

Webhook receivers

Each provider's webhook payload becomes a typed Pascal record — Stripe, GitHub, Twilio, Slack — with validation and idempotency baked in.

Legacy modernisation

Wrap an old DataSnap or RemObjects back-end behind a clean OpenAPI surface without rewriting the business logic.

BFF (Backend-for-Frontend)

Aggregate two or three upstream APIs behind one consumer-shaped spec — your SPA or mobile app talks to a single, typed endpoint.

Pairs With

OpenAPI Parser

Load any external spec into the same model the server uses — same validation, same type system, same security primitives.

Pre-built cloud SDKs

1,195+ generated SDKs for AWS, Azure, GCP, Stripe, GitHub, Kubernetes and more — your server can call any of them with the same component family.

sgcWebSockets

WebSocket, MQTT, AMQP, WebRTC, AI/LLM, IoT — everything the HTTP server can host alongside your REST surface.

sgcSign

Sign request and response bodies with XAdES / PAdES / CAdES for regulated industries — eIDAS-grade integrity on every operation.

Build Your First OpenAPI Server in Minutes

Download the free trial. The full server, both UIs, every auth scheme — no feature limits, no time bomb during evaluation.