TypeSpec
Design APIs
 
Design your data up front and generate schemas, API specifications, client / server code,
      docs, and more.
 import "@typespec/http";
using Http;
model Store {  name: string;  address: Address;}
model Address {  street: string;  city: string;}
@route("/stores")interface Stores {  list(@query filter: string): Store[];  read(@path id: Store): Store;}openapi: 3.0.0info:  title: (title)  version: 0.0.0tags: []paths:  /stores:    get:      operationId: Stores_list      parameters:        - name: filter          in: query          required: true          schema:            type: string      responses:        '200':          description: The request has succeeded.          content:            application/json:              schema:                type: array                items:                  $ref: '#/components/schemas/Store'  /stores/{id}:    get:      operationId: Stores_read      parameters:        - name: id          in: path          required: true          schema:            $ref: '#/components/schemas/Store'      responses:        '200':          description: The request has succeeded.          content:            application/json:              schema:                $ref: '#/components/schemas/Store'components:  schemas:    Address:      type: object      required:        - street        - city      properties:        street:          type: string        city:          type: string    Store:      type: object      required:        - name        - address      properties:        name:          type: string        address:          $ref: '#/components/schemas/Address'import "@typespec/json-schema";
using JsonSchema;
@jsonSchemanamespace Schemas;
model Person {  name: string;  address: Address;  @uniqueItems nickNames?: string[];  cars?: Car[];}
model Address {  street: string;  city: string;  country: string;}
model Car {  kind: "ev" | "ice";  brand: string;  @minValue(1900) year: int32;}$schema: https://json-schema.org/draft/2020-12/schema$id: schema.yaml$defs:  Address:    $schema: https://json-schema.org/draft/2020-12/schema    $id: Address    type: object    properties:      street:        type: string      city:        type: string      country:        type: string    required:      - street      - city      - country  Car:    $schema: https://json-schema.org/draft/2020-12/schema    $id: Car    type: object    properties:      kind:        anyOf:          - type: string            const: ev          - type: string            const: ice      brand:        type: string      year:        type: integer        minimum: 1900        maximum: 2147483647    required:      - kind      - brand      - year  Person:    $schema: https://json-schema.org/draft/2020-12/schema    $id: Person    type: object    properties:      name:        type: string      address:        $ref: Address      nickNames:        type: array        items:          type: string        uniqueItems: true      cars:        type: array        items:          $ref: Car    required:      - name      - addressimport "@typespec/protobuf";
using Protobuf;
@package({  name: "addressbook",})namespace AddressBook;
enum PhoneType {  MOBILE: 0,  HOME: 1,  WORK: 2,}
model PhoneNumber {  @field(1) number: string;  @field(2) type: PhoneType;}
model Person {  @field(1) name: string;  @field(2) id: int32;  @field(3) email: string;  @field(4) phones: PhoneNumber[];  @field(5) last_updated: WellKnown.Timestamp;}// Generated by Microsoft TypeSpec
syntax = "proto3";
package addressbook;
import "google/protobuf/timestamp.proto";
enum PhoneType {  MOBILE = 0;  HOME = 1;  WORK = 2;}
message PhoneNumber {  string number = 1;  PhoneType type = 2;}
message Person {  string name = 1;  int32 id = 2;  string email = 3;  repeated PhoneNumber phones = 4;  google.protobuf.Timestamp last_updated = 5;}Why TypeSpec
API-First for developers
With TypeSpec, remove the handwritten files that slow you down, and generate
          standards-compliant API schemas in seconds.
 
  
 Lightweight language for defining APIs
 Inspired by TypeScript, TypeSpec is a minimal language that helps developers describe API shapes in a familiar way.
   Learn more →
    
  
 Easy integration with your toolchain
 Write TypeSpec, emit to various formats and integrate with their ecosystems.
   
  
 Multi-protocol support
 TypeSpec's standard library includes support for OpenAPI 3.0, JSON Schema 2020-12 and Protobuf.
   Learn more →
   ~ /my-project tsp init? Select a templateEmpty project> REST API
 
   
  Productivity
 Streamline your OpenAPI workflow
 Benefit from a huge ecosystem of OpenAPI tools for configuring API gateways, generating code, and validating your data.
  
 
Generate OpenAPI from TypeSpec
Learn more →
import "@typespec/http";
using Http;
model Pet {  name: string;  age: int32;}
model Store {  name: string;  address: Address;}
model Address {  street: string;  city: string;}
@route("/pets")interface Pets {  list(@query filter: string): Pet[];  create(@body pet: Pet): Pet;  read(@path id: string): Pet;}
@route("/stores")interface Stores {  list(@query filter: string): Store[];  read(@path id: string): Store;}openapi: 3.0.0info:  title: (title)  version: 0.0.0tags: []paths:  /pets:    get:      operationId: Pets_list      parameters:        - name: filter          in: query          required: true          schema:            type: string      responses:        '200':          description: The request has succeeded.          content:            application/json:              schema:                type: array                items:                  $ref: '#/components/schemas/Pet'    post:      operationId: Pets_create      parameters: []      responses:        '200':          description: The request has succeeded.          content:            application/json:              schema:                $ref: '#/components/schemas/Pet'      requestBody:        required: true        content:          application/json:            schema:              $ref: '#/components/schemas/Pet'  /pets/{id}:    get:      operationId: Pets_read      parameters:        - name: id          in: path          required: true          schema:            type: string      responses:        '200':          description: The request has succeeded.          content:            application/json:              schema:                $ref: '#/components/schemas/Pet'  /stores:    get:      operationId: Stores_list      parameters:        - name: filter          in: query          required: true          schema:            type: string      responses:        '200':          description: The request has succeeded.          content:            application/json:              schema:                type: array                items:                  $ref: '#/components/schemas/Store'  /stores/{id}:    get:      operationId: Stores_read      parameters:        - name: id          in: path          required: true          schema:            type: string      responses:        '200':          description: The request has succeeded.          content:            application/json:              schema:                $ref: '#/components/schemas/Store'components:  schemas:    Address:      type: object      required:        - street        - city      properties:        street:          type: string        city:          type: string    Pet:      type: object      required:        - name        - age      properties:        name:          type: string        age:          type: integer          format: int32    Store:      type: object      required:        - name        - address      properties:        name:          type: string        address:          $ref: '#/components/schemas/Address'Ecosystem
 Ensure data consistency
 Define common models to use across your APIs, use the JSON schema emitter to get the JSON schema for your types and use them to validate your data.
  
 
JSON schema emitter reference
Learn more →
import "./common.tsp";
namespace MyOrg.Accounts;
using MyOrg.Types;
model Account {  id: id;  firstName: string;  lastName: string;  createdAt: utcDateTime;
  // Use imported type by name only when using `using`  ssn: ssn;
  // Or use the fully qualified name  email: MyOrg.Types.email;
  balance: Amount;}
model Amount {  value: decimal128;  currency: Currency;}
// Create your own error types by extending the Error typemodel AccountError is Error<"duplicate-account" | "invalid-account">;
op createAccount(account: Account): Account;
op charge(accountId: id, amount: Amount): void | AccountError;namespace MyOrg.Types;
@format("uuid")scalar uuid extends string;
// Defined a standard id type that all models can usescalar id extends uuid;
@pattern(".+\\@.+\\..+")scalar email extends string;
@pattern("^\\d{3}-\\d{2}-\\d{4}$")scalar ssn extends string;
/** * Standard error response */model Error<T extends string> {  code: T;  message: string;  details?: Record<string>;  timestamp: utcDateTime;}
enum Currency {  USD,  EUR,  GBP,  CAD,  JPY,}Tooling
 Full language support in VS Code and Visual Studio
 TypeSpec provides built-in support for many common editor features such as syntax highlighting, code completion, and more.
  
 
Check out our available tooling
Learn more →
 
   
  Extensibility
 Generate assets in many formats
 TypeSpec is built around extensibility - you can write your own emitter or add custom metadata using a new decorator.
  
 
Getting started with writing a library
Learn more →
extern dec group(target: TypeSpec.Reflection.Model, name: valueof string);import { DecoratorContext, EmitContext, Model, resolvePath } from "@typespec/compiler";
export async function $onEmit(context: EmitContext) {  const outputDir = resolvePath(context.emitterOutputDir, "hello.txt");  await context.program.host.writeFile(outputDir, "hello world!");}
const groupKey = Symbol.for("my-library/group");export function $group(context: DecoratorContext, target: Model, value: string) {  context.program.stateMap(groupKey).set(target, value);}Start your TypeSpec journey
Install the TypeSpec CLI or check out the playground to get started.