Skip to content

OpenAPI Client Provider

OpenApiClientProvider is a generative F# Type Provider, built on top of Microsoft.OpenApi.Readers schema parser that supports 3.0 and 2.0 schema formats.

fsharp
open SwaggerProvider

let [<Literal>] Schema = "https://petstore.swagger.io/v2/swagger.json"
type PetStore = OpenApiClientProvider<Schema>
let client = PetStore.Client()

Parameters

OpenApiClientProvider supports the following configuration parameters

ParameterDescription
SchemaUrl or Path to Swagger schema file.
IgnoreOperationIdDo not use operationsId and generate method names using path only. Default value false.
IgnoreControllerPrefixDo not parse operationsId as <controllerName>_<methodName> and generate one client class for all operations. Default value true.
PreferNullableProvide Nullable<_> for not required properties, instead of Option<_>. Defaults value false.
PreferAsyncGenerate async actions of type Async<'T> instead of Task<'T>. Defaults value false.
SsrfProtectionEnable SSRF protection (blocks HTTP and localhost). Set to false for development/testing. Default value true.
IgnoreParseErrorsContinue generating the provider even when the OpenAPI parser reports validation errors (e.g. vendor extensions or non-strictly-compliant schemas). Warnings are printed to stderr. Default value false.

More configuration scenarios are described in Customization section

Security (SSRF Protection)

By default, SwaggerProvider blocks HTTP URLs and localhost/private IP addresses to prevent SSRF attacks.

For development and testing with local servers, disable SSRF protection:

fsharp
// Development: Allow HTTP and localhost
type LocalApi = OpenApiClientProvider<"http://localhost:5000/swagger.json", SsrfProtection=false>

// Production: HTTPS with SSRF protection (default)
type ProdApi = OpenApiClientProvider<"https://api.example.com/swagger.json">

Warning: Never set SsrfProtection=false in production code.

Non-Strictly-Compliant Schemas (IgnoreParseErrors)

Some OpenAPI schemas generated by tools such as NSwag may include extensions or properties that are technically invalid (e.g. nullable: true at the parameter level). By default, SwaggerProvider aborts with an error when the Microsoft.OpenApi parser reports such validation errors.

Set IgnoreParseErrors=true to continue generating the type provider despite these errors. Validation warnings are printed to stderr so they remain visible:

fsharp
// NSwag-generated schema with non-standard nullable annotations
type MyApi = OpenApiClientProvider<"https://example.com/swagger.json", IgnoreParseErrors=true>

Note: Only use IgnoreParseErrors=true when you trust the schema source. Suppressing errors may hide genuine schema problems that could affect the generated client.

CancellationToken Support

Every generated method automatically includes an optional cancellationToken: CancellationToken parameter (defaults to CancellationToken.None). This allows you to cancel long-running HTTP requests:

fsharp
open System
open System.Threading
open SwaggerProvider

let [<Literal>] Schema = "https://petstore.swagger.io/v2/swagger.json"
type PetStore = OpenApiClientProvider<Schema>

let client = PetStore.Client()

task {
    // Cancel after 5 seconds
    use cts = new CancellationTokenSource(TimeSpan.FromSeconds(5.0))
    let! pet = client.GetPetById(42L, cancellationToken = cts.Token)
    printfn $"Pet: {pet}"
}
|> _.Result

Sample

fsharp
open System
open System.Net.Http
open SwaggerProvider

let [<Literal>] Schema = "https://petstore.swagger.io/v2/swagger.json"
// By default provided methods return Task<'a>
// and use Option<'a> for optional params
type PetStore = OpenApiClientProvider<Schema>

[<EntryPoint>]
let main argv =
    // `UseCookies = false` is required if you use Cookie Parameters
    let handler = new HttpClientHandler(UseCookies = false)
    // `BaseAddress` uri should end with '/' because TP generates relative URIs
    let baseUri = Uri("https://petstore.swagger.io/v2/")
    use httpClient = new HttpClient(handler, true, BaseAddress = baseUri)
    // You can provide your instance of `HttpClient` to the provided API client
    // or change it any time at runtime using `client.HttpClient` property
    let client = PetStore.Client(httpClient)

    task {
        // Create a new instance of the provided type and add to store
        let pet = PetStore.Pet(Id = Some(24L), Name = "Shani")
        do! client.AddPet(pet)

        // Request data back and deserialize to the provided type
        let! myPet = client.GetPetById(24L)
        printfn "Waw, my name is %A" myPet.Name
    }
    |> Async.AwaitTask
    |> Async.RunSynchronously
    0