OpenAPI Specification
We're expecting the passed OpenAPI document to adhere to the Swagger 2.0, OpenAPI 3.0, OpenAPI 3.1 or OpenAPI 3.2 specification.
On top of that, we've added a few things for your convenience:
Editor completion and version compatibility
The Scalar App editor offers OpenAPI 3.2 completion and structural diagnostics for documents declaring either OpenAPI 3.1 or 3.2. This permissive editing policy helps you work with newer fields, but the absence of editor errors does not certify that a document conforms to its declared OpenAPI version.
For example, the editor accepts itemSchema, additionalOperations, and style: cookie even when the document still declares openapi: 3.1.0. Those fields are not part of OpenAPI 3.1, and tools that validate that version may reject the document. Editor completion does not automatically change the declared version.
Before using OpenAPI 3.2-only fields, migrate the document to OpenAPI 3.2 and explicitly set a matching version such as openapi: 3.2.0. Check that your validators, generators, and other consumers support that version, and validate the resulting document with a validator that respects the declared version. If you need to remain compatible with OpenAPI 3.1 consumers, keep the declaration and field usage within OpenAPI 3.1.
Whole-query parameters (OpenAPI 3.2)
An in: querystring parameter describes the entire query string. Its name is documentary and is not added to the request URL. Scalar uses the parameter's content media type to serialize its value.
For content other than application/x-www-form-urlencoded, Scalar percent-encodes the serialized value, including JSON delimiters. For example, a JSON value of {"limit":2} produces ?%7B%22limit%22%3A2%7D in both requests and generated code samples.
To supply URI-ready content with its encoding preserved, set serializedValue in an example on the parameter itself:
parameters:
- name: search
in: querystring
required: true
content:
application/json:
schema:
type: object
properties:
limit:
type: integer
examples:
default:
serializedValue: '%7B%22limit%22%3A2%7D'
A serializedValue under a media type describes serialized media content and still undergoes URI encoding. The parameter-level example bypasses that step; provide any escaping required by the target server and HTTP client yourself.
OpenAPI 3.2 does not allow mixing in: querystring and named in: query parameters. For existing descriptions containing both, Scalar preserves the values and emits the whole-query content first, followed by named query parameters and query authentication parameters. Duplicate keys are preserved: a whole-query status=available and a named status=sold produce ?status=available&status=sold. Scalar does not choose which value wins; that depends on the receiving server. The editor explains why additional named parameters cannot be added while keeping existing rows editable.
Custom Specification Extensions
You can add custom specification extensions (starting with a x-) through our plugin API.
x-scalar-environments
You can specify predefined environment variables for the API Client/References to consume and use:
x-scalar-environments:
production:
description: "Production environment"
color: "#0082D0"
# Variables are saved directly to the specification
variables:
userId:
description: "User ID"
default: "1234567890"
apiUrl:
description: "API URL"
default: "https://api.production.example.com"
staging:
description: "Staging environment"
variables:
userId: "1234567890"
apiUrl:
description: "API URL"
default: "https://api.staging.example.com"
x-scalar-active-environment
You can also specify the default active environment a user will have :) if there's none set here we pick the first from the x-scalar-environments to be the default
x-scalar-active-environment: staging
x-codeSamples
We provide examples for a lot of popular HTTP clients and frameworks. For something completely custom, for example to show the use of your own SDK, you can use x-codeSamples:
openapi: 3.1.0
info:
title: Val Town API
version: 1.0
paths:
'/v1/eval':
post:
+ x-codeSamples:
+ - label: ValTown JS SDK
+ lang: JavaScript
+ source: |-
+ import ValTown from '@valtown/sdk';
+
+ const valTown = new ValTown();
+
+ async function main() {
+ const valRunAnonymousResponse = await valTown.vals.runAnonymous({ code: 'console.log(1);' });
+
+ console.log(valRunAnonymousResponse);
+ }
+
+ main();
Link code samples to request examples
Set example to a key in requestBody.content[contentType].examples and set contentType to that media type. Samples with the same lang and label share one language option. The example switcher chooses the matching sample without changing the selected language.
openapi: 3.1.0
info: { title: Widgets API, version: '1.0' }
paths:
/widgets:
post:
requestBody:
content:
application/json:
schema: { type: object }
examples:
simple: { value: { name: Basic } }
detailed: { value: { name: Premium, description: More features } }
responses:
'200': { description: Created }
x-codeSamples:
- lang: Python
example: simple
contentType: application/json
source: client.widgets.create(name="Basic")
- lang: Python
example: detailed
contentType: application/json
source: client.widgets.create(name="Premium", description="More features")
The same fields work with x-scalar-examples, x-code-samples, and x-custom-examples. Omit contentType to use a sample for any media type with that example key. The contentType must exactly match the request body media type key, including any parameters: application/json; charset=utf-8 does not match application/json. Static samples without example keep their own language-menu entries. Their source stays unchanged when switching body examples, but the switcher still controls which example opens in Test Request. If a linked sample is missing for the selected example, Scalar displays an unavailable message.
Code samples from other tools
If your OpenAPI document is generated by another tool, we also read code samples from the extensions those tools write. When more than one of these is present on an operation, we use the highest-priority source only (instead of showing duplicates from every tool). Priority, highest first:
x-scalar-examplesx-stainless-snippets(overridesx-stainless-examples)x-stainless-examplesx-readme(viax-readme.code-samples)x-codeSamples/x-code-samples/x-custom-examples
x-scalar-examples uses the same shape as x-codeSamples (a list of lang / label / source entries):
paths:
'/accounts':
get:
x-scalar-examples:
- lang: python
label: List accounts
source: client.accounts.list()
x-stainless-examples is an example (or array of examples) with an optional title and a request map of source code keyed by language. The title is used as the label in the picker.
paths:
'/accounts':
get:
x-stainless-examples:
title: List active accounts
request:
python: client.accounts.list(status="active")
node: await client.accounts.list({ status: 'active' });
x-stainless-snippets is a map of source code keyed by language:
paths:
'/accounts':
get:
x-stainless-snippets:
python: client.accounts.list()
node: await client.accounts.list();
x-readme.code-samples is a list of samples using ReadMe's field names (language, code, name). ReadMe's correspondingExample refers to a response example, so it is not used to link samples to request body examples:
paths:
'/accounts':
get:
x-readme:
code-samples:
- language: curl
name: Custom cURL
code: curl https://api.example.com/accounts
x-example / x-examples
For Swagger 2.0 documents, we support x-example and x-examples extensions on body parameters. These bring OpenAPI 3.x example functionality to older specifications.
Use x-example for a single example value:
swagger: '2.0'
paths:
'/planets':
post:
consumes:
- application/json
parameters:
- in: body
name: body
schema:
type: object
x-example:
application/json:
name: Earth
Use x-examples for multiple named examples with summaries:
swagger: '2.0'
paths:
'/planets':
post:
consumes:
- application/json
parameters:
- in: body
name: body
schema:
type: object
x-examples:
application/json:
earth-example:
summary: Earth planet
value:
name: Earth
mars-example:
summary: Mars planet
value:
name: Mars
externalValue
externalValue is a standard OpenAPI field on an Example Object. It lets you keep large request or response examples outside of your OpenAPI document and point to them by URL instead. This is useful when a single document would otherwise contain hundreds or thousands of big example payloads.
Scalar fetches an external example only when its selected preview becomes visible or you open it in Test Request. Other examples, including examples on hidden operations, are not downloaded during document loading. The request preview, generated code snippets, and Test Request use the same resolved payload.
Successful downloads are cached for the loaded document. Selecting an example again reuses its payload; replacing the document clears the cache. While an example loads, Scalar shows a loading message. If the download fails, you can retry. Sending the request is disabled until its selected example is ready.
paths:
'/shipments':
post:
requestBody:
content:
application/json:
examples:
shipper-standard:
summary: Shipper Standard
externalValue: /examples/post-shipment/shipper-standard.json
The referenced endpoint returns the raw example payload:
{
"shippingType": "Shipper_001",
"packages": []
}
A few things to keep in mind:
valueandexternalValueare mutually exclusive. If both are present,valueis used.- Relative URLs (like the one above) are resolved against the URL your document was loaded from.
- The referenced URL must be reachable by the browser (CORS applies), and should return JSON or YAML.
Nested tags (OpenAPI 3.2)
In OpenAPI 3.2, you can nest tags with the native parent field instead of x-tagGroups. Set parent to the name of another tag declared in the document. Tags can be nested across multiple levels, and a parent tag can have operations of its own alongside its child tags.
Use summary for a readable tag title in the navigation and section headings. Operations still reference the tag's name. If x-displayName is also set, it takes precedence over summary.
openapi: 3.2.0
info:
title: Example
version: '1.0.0'
tags:
- name: galaxy
summary: Galaxy
- name: planets
summary: Planets
parent: galaxy
- name: moons
summary: Moons
parent: planets
paths:
/planets:
get:
summary: Get all planets
tags:
- planets
responses:
'200':
description: A list of planets
/moons:
get:
summary: Get all moons
tags:
- moons
responses:
'200':
description: A list of moons
This creates the hierarchy Galaxy → Planets → Moons. The Planets section contains both its own operation and the nested Moons section.
When at least one parent relationship points to a declared tag without forming a cycle, Scalar uses native nesting for the document instead of x-tagGroups. Unknown parents, self-references, and circular relationships do not create nesting. If no valid nesting relationship remains, Scalar falls back to x-tagGroups.
x-displayName
You can overwrite tag names with x-displayName.
openapi: 3.1.0
info:
title: Example
version: 1.0
tags:
- name: pl4n3t5
+ x-displayName: planets
paths:
'/planets':
get:
summary: Get all planets
tags:
- pl4n3t5
x-tagGroups
You can group your tags with x-tagGroups. This remains supported for existing API descriptions and OpenAPI versions before 3.2. For OpenAPI 3.2, use native nested tags with parent instead.
openapi: 3.1.0
info:
title: Example
version: 1.0
tags:
- name: planets
+x-tagGroups:
+ - name: galaxy
+ tags:
+ - planets
paths:
'/planets':
get:
summary: Get all planets
tags:
- planets
x-scalar-ignore
You can hide operations and webhooks from the reference with x-scalar-ignore.
openapi: 3.1.0
info:
title: Example
version: 1.0
paths:
'/planets':
get:
summary: Get all planets
post:
summary: Create a new planet
+ x-scalar-ignore: true
Or to hide a tag and the operations under it:
openapi: 3.1.0
info:
title: Example
version: 1.0
tags:
- name: planets
+ x-scalar-ignore: true
paths:
'/planets':
get:
summary: Get all planets
tags:
- planets
post:
summary: Create a new planet
tags:
- planets
You can also hide authentication. Add x-scalar-ignore to a whole security scheme to drop it from the auth selector, or to a single OAuth2 flow to hide just that flow's tab. This is handy for flows that cannot run in the browser, like Client Credentials, which usually fails on CORS:
components:
securitySchemes:
oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.example.com/authorize
tokenUrl: https://auth.example.com/token
scopes: {}
clientCredentials:
tokenUrl: https://auth.example.com/token
scopes: {}
x-scalar-ignore: true
Aliases: x-internal
x-additionalPropertiesName
OpenAPI allows description of "additionalProperties" that may be included in a schema. Their names are unknown, but the field types can be added to the API description so that producers and consumers understand whether additional fields are permitted and any additional rules that apply.
Since the field names are not specified, they are displayed with a generic name in the API reference documentation. Use x-additionalPropertiesName to display a more meaningful name in this scenario.
The following example shows a schema that accepts any fields as long as the values are numbers between 0-100, for a set of sensors reporting fill levels:
components:
schemas:
FillLevel:
type: object
properties:
reportTime:
type: string
format: date-time
description: Report creation time.
required:
- reportTime
additionalProperties:
x-additionalPropertiesName: percentage
type: integer
minimum: 0
maximum: 100
The additional properties appear in the documentation as percentage*.
x-order
You can control the display order of schema properties with x-order. Properties with x-order are sorted by their numeric value (ascending) and displayed before properties without x-order.
openapi: 3.1.0
info:
title: Example
version: 1.0
components:
schemas:
Planet:
type: object
properties:
name:
type: string
+ x-order: 1
description:
type: string
+ x-order: 3
diameter:
type: number
+ x-order: 2
In this example, properties will be displayed in the order: name, diameter, description.
x-order also controls the order of OAuth2 flow tabs in the auth section. Flows with a lower x-order appear first, and the first tab is selected by default — so giving a flow the lowest x-order both moves it to the front and makes it the default:
components:
securitySchemes:
oauth2:
type: oauth2
flows:
implicit:
authorizationUrl: https://auth.example.com/authorize
scopes: {}
x-order: 2
authorizationCode:
authorizationUrl: https://auth.example.com/authorize
tokenUrl: https://auth.example.com/token
scopes: {}
x-order: 1
Here the authorizationCode tab appears first and is selected by default.
x-scalar-stability
You can show the stability of an endpoint by setting the x-scalar-stability to either stable, experimental or deprecated. The native deprecated property will take precedence.
openapi: 3.1.0
info:
title: Example
version: 1.0
paths:
'/planets':
get:
summary: Get all planets
post:
summary: Create a new planet
+ x-scalar-stability: 'experimental'
x-badges
You can add badges to operations to use as indicators in documentation. Each operation can have multiple badges, and the displayed color is also configurable. The following example sets badges on the GET /hello-world operation:
openapi: 3.1.0
info:
title: x-badges
version: 1.0.0
paths:
/hello-world:
get:
summary: Hello World
+ x-badges:
+ - name: 'Alpha'
+ - name: 'Beta'
+ position: before
+ - name: 'Gamma'
+ position: after
+ color: '#ffcc00'
| Option | Type | Description |
|---|---|---|
| name | string | REQUIRED. The text that displays in the badge. |
| position | string | The position of the badge in relation to the header. Possible values: before, after. The default value is after. |
| color | string | The color of the badge. It can be defined in various formats such as color keywords, RGB, RGBA, HSL, HSLA, and Hexadecimal. |
x-enum-descriptions
You can add descriptions to enum values with x-enum-descriptions:
openapi: 3.1.0
info:
title: Example
version: 1.0
components:
schemas:
CustomerCancellationReason:
type: string
enum:
- missing_features
- too_expensive
- unused
- other
+ x-enum-descriptions:
+ missing_features: Missing features
+ too_expensive: Too expensive
+ unused: Unused
+ other: Other
Aliases: x-enumDescriptions
x-enum-varnames
You can provide variable names for enum values with x-enum-varnames. These names will be displayed alongside the enum values in the format value = varname:
openapi: 3.1.0
info:
title: Example
version: 1.0
components:
schemas:
HttpStatusCode:
type: integer
enum:
- 100
- 200
- 300
- 400
- 500
+ x-enum-varnames:
+ - Continue
+ - OK
+ - MultipleChoices
+ - BadRequest
+ - InternalServerError
This will display as: 100 = Continue, 200 = OK, 300 = MultipleChoices, etc.
Aliases: x-enumNames
x-scalar-sdk-installation
We generate custom code examples for all languages, but you might have a custom SDK for your API. Provide installation instructions in the header and they replace the generic HTTP clients in the introduction.
Each entry has a lang (used as the tab label and to pick a matching language icon) and a description. The description supports Markdown, including fenced code blocks with syntax highlighting, so a single tab can show multiple snippets (for example Maven and Gradle for Java).
openapi: 3.1.0
info:
title: Example
version: 1.0
+ x-scalar-sdk-installation:
+ - lang: TypeScript
+ description: |-
+ Install our **Custom SDK** from npm:
+
+ ```sh
+ npm install @your-awesome-company/sdk
+ ```
+ - lang: Java
+ description: |-
+ Add the dependency with Maven:
+
+ ```xml
+ <dependency>
+ <groupId>com.your-awesome-company</groupId>
+ <artifactId>sdk</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ ```
+
+ …or with Gradle:
+
+ ```groovy
+ implementation 'com.your-awesome-company:sdk:1.0.0'
+ ```
| Option | Type | Description |
|---|---|---|
| lang | string | REQUIRED. The language or platform of the SDK (for example TypeScript, Java, Python). |
| description | string | The installation instructions for this language. Supports Markdown, including fenced code blocks. |
x-scalar-links
Add named links next to the contact, license and terms of service links in the introduction. This is handy for the legal texts that some countries require on public websites, like a privacy policy or an imprint.
openapi: 3.1.0
info:
title: Example
version: 1.0
+ x-scalar-links:
+ - name: Privacy Policy
+ url: https://example.com/privacy
+ - name: Imprint
+ url: https://example.com/imprint
| Option | Type | Description |
|---|---|---|
| name | string | REQUIRED. The label to display for the link. |
| url | string | REQUIRED. The URL the link points to. |
x-pre-request
Add pre-request scripts to operations or at the document level. Scripts run before the request is sent and can modify headers, set variables, or prepare authentication. See Scripts in the API Client for the full guide.
On an operation:
openapi: 3.1.0
info:
title: Example
version: 1.0
paths:
'/users':
get:
summary: Get all users
+ x-pre-request: |-
+ pm.environment.set('timestamp', new Date().toISOString())
On the document (runs before every operation):
openapi: 3.1.0
info:
title: Example
version: 1.0
+x-pre-request: |-
+ pm.request.headers.add({
+ key: 'X-Request-Id',
+ value: 'req-' + Date.now()
+ })
When both document-level and operation-level scripts are present, the document-level script runs first.
x-post-response
Add post-response scripts to operations to automatically validate API responses. Scripts use a Postman-compatible syntax and run after each request in the API Client.
openapi: 3.1.0
info:
title: Example
version: 1.0
paths:
'/planets':
get:
summary: Get all planets
+ x-post-response: |-
+ pm.test("Status code is 200", () => {
+ pm.response.to.have.status(200)
+ })
You can add multiple assertions in a single script:
openapi: 3.1.0
info:
title: Example
version: 1.0
paths:
'/planets':
post:
summary: Create a planet
+ x-post-response: |-
+ pm.test("Returns 201", () => {
+ pm.expect(pm.response.code).to.be.oneOf([201, 202])
+ })
+ pm.test("Response is valid JSON", () => {
+ const data = pm.response.json()
+ pm.expect(data).to.be.an('object')
+ })
See Testing in the API Client for all available assertions and the full pm API reference.
XML examples
XML examples use the schema's xml metadata for element names, attributes, namespaces,
and array wrappers. Automatic generation has depth and node limits to keep large API
descriptions responsive. When a response example exceeds these limits, the response
panel explains that a complete serialized example is needed.
To display an existing XML payload without generating a tree, use an OpenAPI 3.2
media-level serializedValue. It is preserved exactly, including whitespace:
openapi: 3.2.0
info:
title: XML example
version: 1.0.0
paths:
/pets:
get:
responses:
'200':
description: Pets
content:
application/xml:
examples:
pets:
serializedValue: '<pets><pet id="1">Milo</pet></pets>'
For OpenAPI 3.0 or 3.1, use a string value in the media-level Example Object.
Schema-level string examples represent data and are escaped as XML text.