dotnet-rivet 0.35.0

There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global dotnet-rivet --version 0.35.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local dotnet-rivet --version 0.35.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=dotnet-rivet&version=0.35.0
                    
nuke :add-package dotnet-rivet --version 0.35.0
                    

<p align="center"> <h1 align="center">Rivet</h1> <p align="center"> <a href="https://www.nuget.org/packages/Rivet.Attributes"><img src="https://img.shields.io/nuget/v/Rivet.Attributes?label=Rivet.Attributes" alt="NuGet" /></a> <a href="https://www.nuget.org/packages/dotnet-rivet"><img src="https://img.shields.io/nuget/v/dotnet-rivet?label=dotnet-rivet" alt="NuGet" /></a> <img src="https://img.shields.io/badge/license-MIT-blue" alt="License" /> </p> </p>

Your C# is the contract. Rivet reads your C# types and ASP.NET endpoints with Roslyn and emits an OpenAPI 3.1 specification — no attributes-on-everything, no runtime reflection, no drift between your declared C# types and what the spec says.

Rivet maps what actually survives the wire boundary. The OpenAPI ecosystem does the rest: TypeScript types via openapi-typescript, a typed client via openapi-fetch, Zod schemas via openapi-zod-client, docs via any OpenAPI renderer.

oRPC gives you this when your server is TypeScript. Rivet gives you the same DX when your server is .NET.

Install

dotnet add package Rivet.Attributes
dotnet tool install --global dotnet-rivet

Generate

dotnet rivet --project path/to/Api.csproj --output ./generated

This writes ./generated/openapi.json — an OpenAPI 3.1 spec derived from your compiled C# (Roslyn semantic model, not runtime reflection). Omit --output to preview the spec on stdout. --title, --version, and --server set the spec's info and servers metadata (CLI reference).

C# Types → OpenAPI Schemas

public enum WorkItemStatus { Draft, Open, InProgress, Review, Done, Cancelled }

public sealed record Email(string Value);

public sealed record MemberDto(Guid Id, string Name, Email Email, string Role);
// components/schemas (excerpt)
{
  "WorkItemStatus": {
    "type": "string",
    "enum": ["draft", "open", "inProgress", "review", "done", "cancelled"]
  },
  "Email": { "type": "string", "x-rivet-brand": "Email" },
  "MemberDto": {
    "type": "object",
    "properties": {
      "id": { "type": "string", "format": "uuid" },
      "name": { "type": "string" },
      "email": { "$ref": "#/components/schemas/Email" },
      "role": { "type": "string" }
    },
    "required": ["id", "name", "email", "role"]
  }
}

Value-object brands, generics (monomorphised), nullability, validation attributes ([Range], [StringLength], [RegularExpression], ...), descriptions, and examples all flow into the spec. So do [JsonPolymorphic]/[JsonDerivedType] hierarchies (oneOf + discriminator) and dictionary key types (propertyNames for enum, branded, and primitive keys) — plus x-rivet-* vendor extensions that preserve C#-level fidelity (brands, generics, contract names) through the spec (vendor extensions reference, type mapping).

ASP.NET Endpoints → OpenAPI Operations

Rivet works with ordinary ASP.NET controllers. Mark the endpoints you want surfaced and the operation is derived from the real transport shape:

[ApiController]
[Route("api/tasks")]
public sealed class TasksController : ControllerBase
{
    [RivetEndpoint]
    [HttpGet("{id:guid}")]
    [ProducesResponseType(typeof(TaskDetailDto), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(NotFoundDto), StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Get(Guid id, CancellationToken ct)
    {
        return Ok(default(TaskDetailDto));
    }
}

becomes GET /api/tasks/{id} with a typed 200 (TaskDetailDto) and 404 (NotFoundDto) response — route constraints normalised, params classified (route/query/header/body/form/file — [FromHeader] maps to in: header), multipart and form-encoded bodies handled.

Consume the Spec (TypeScript)

The generated spec plugs straight into the OpenAPI TypeScript ecosystem:

npx openapi-typescript ./generated/openapi.json -o ./src/api/schema.d.ts
npm install openapi-fetch
import createClient from "openapi-fetch";
import type { paths } from "./api/schema";

const api = createClient<paths>({ baseUrl: "https://api.example.com" });

// Fully type-safe: path, params, body, and per-status responses all inferred.
const { data, error, response } = await api.GET("/api/tasks/{id}", {
  params: { path: { id: taskId } },
});

if (error) {
  // narrowed to NotFoundDto for the declared 404
  console.error(error.message);
}

Want runtime validation? Generate Zod schemas from the same spec with openapi-zod-client.

Advanced Features

Rivet also supports:

  • contract-driven APIs with [RivetContract] — compiler-enforced single source of truth for routes, inputs, outputs, and error responses, with runtime Invoke helpers and coverage checking
  • minimal API hosts
  • file endpoints with query-string auth (file uploads & downloads)
  • headers as contract concepts — [RivetHeader]/[FromHeader] request headers and .WithResponseHeader(...) response headers (attributes, route definition API)
  • stable RIVnnnn diagnostic IDs on every warning — grep or baseline by ID (diagnostics reference)
  • OpenAPI import — a one-shot onboarding scaffold for existing APIs: it generates C# contracts once, with loud diagnostics for anything it can't represent (supported profile); the C# then becomes the source of truth
  • round-trips: emit → import → emit produces an equivalent spec (security scheme definitions come from --security, not the original spec)
  • the TypeScript-first sibling project rivet-ts (Hono runtime + the same OpenAPI pipeline via the bundled Rivet binary)

What Rivet Enforces (and What It Doesn't)

Rivet's guarantees are spec-time, not runtime. The C# compiler enforces handler input/output types on .Invoke(), and contract Invoke validates that returned status codes (and, for ASP.NET typed results, the payload's C# type) match the declaration. Rivet does not validate request or response data at runtime:

  • constraint attributes ([Range], [StringLength], ...) flow into the spec but are not checked by Rivet at runtime — enforcement is the host framework's job, and the docs have the recipes ([ApiController] model validation on controller hosts, Validator.TryValidateObject on minimal-API hosts; [RivetConstraints] is a ValidationAttribute and participates in both)
  • response bodies are not shape-checked — extra properties on a returned object serialize to the wire
  • declared request/response headers are spec-only — Rivet never binds, sets, or validates them
  • Define.File endpoints have no runtime enforcement at all

Full statement: Runtime Validation.

Documentation

Start with:

License

MIT

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.46.0 96 10/3/2026
0.45.1 98 9/30/2026
0.45.0 96 9/29/2026
0.44.1 109 9/21/2026
0.44.0 105 9/19/2026
0.43.0 112 9/18/2026
0.42.0 110 9/17/2026
0.41.0 222 7/13/2026
0.40.0 144 7/11/2026
0.39.0 127 7/11/2026
0.38.0 125 6/13/2026
0.37.0 147 6/12/2026
0.36.1 138 6/12/2026
0.36.0 131 6/12/2026
0.35.0 132 6/12/2026
0.34.3 139 5/22/2026
0.34.0 132 4/21/2026
0.33.2 143 4/16/2026
0.33.1 148 4/16/2026
0.33.0 134 4/15/2026
Loading failed