0x · API Governance Rules

0x API Rules

Spectral linting rules defining API design standards and conventions for 0x.

27 Rules error 11 warn 12 info 4
View Rules File View on GitHub

Rule Categories

0x

Rules

error
0x-info-title-prefix
0x specs are titled "0x API" or "0x API" — match that pattern.
$.info.title
warn
0x-info-description-required
Every spec must have an info.description with at least 40 chars.
$.info
error
0x-info-version-required
Spec version MUST be set (e.g. v2 for Swap/Gasless, v1 for Cross-Chain).
$.info
error
0x-server-url-canonical
All 0x APIs are served from https://api.0x.org.
$.servers[*].url
warn
0x-paths-kebab-case
Path segments use kebab-case (allowance-holder, trade-analytics, gasless-approval-tokens, tx-history-beta). Reject snake_case and camelCase.
$.paths.*~
error
0x-paths-no-trailing-slash
Paths must not end with a trailing slash.
$.paths.*~
error
0x-operation-operationid-required
Every operation MUST declare an operationId (used by SDK generators).
$.paths.*[get,post,put,delete,patch]
warn
0x-operation-operationid-namespaced
0x operationIds follow `::::` (e.g. swap::permit2::getQuote, gasless::submit, crossChain::getQuotes). Enforce double-colon namespacing or camelCase verb names.
$.paths.*[get,post,put,delete,patch].operationId
error
0x-operation-summary-required
Every operation MUST have a Title Case summary.
$.paths.*[get,post,put,delete,patch]
warn
0x-operation-description-required
Operation description is required and should be at least 30 chars.
$.paths.*[get,post,put,delete,patch]
error
0x-operation-tags-required
Every operation MUST be tagged with one of: Swap, Gasless, Cross-Chain, Trade Analytics, Sources.
$.paths.*[get,post,put,delete,patch].tags
info
0x-operation-microcks-extension
Operations SHOULD include x-microcks-operation with dispatcher FALLBACK for replayable mock generation.
$.paths.*[get,post,put,delete,patch]
warn
0x-tags-title-case
Tag names use Title Case ("Swap", "Cross-Chain", "Trade Analytics").
$.paths.*[get,post,put,delete,patch].tags[*]
error
0x-header-api-key-required
All 0x API operations require the `0x-api-key` header for authentication.
$.paths.*[get,post,put,delete,patch]
warn
0x-header-version-required
Swap, Gasless, Sources, and Trade Analytics operations require the `0x-version` header (currently `v2`).
$.paths.*[get,post,put,delete,patch]
warn
0x-parameter-camelcase
Query and path parameter names use camelCase (chainId, sellToken, buyToken, sellAmount, taker, tradeHash, includedSources, excludedSources, slippageBps).
$.paths.*[get,post,put,delete,patch].parameters[?(@.in=='query' || @.in=='path')].name
warn
0x-parameter-description-required
All parameters MUST be documented.
$.paths.*[get,post,put,delete,patch].parameters[*]
info
0x-chainid-parameter-required
Almost every 0x endpoint takes a `chainId` query parameter to route the request to the correct EVM chain (or non-EVM virtual chain ID for Solana, HyperCore, Tron in the Cross-Chain API).
$.paths.*[get,post,put,delete,patch].parameters[?(@.in=='query')].name
error
0x-response-200-required
Every operation MUST document a 200 response.
$.paths.*[get,post,put,delete,patch].responses
warn
0x-response-400-recommended
Most 0x operations return 400 for INPUT_INVALID / validation failures — document it.
$.paths.*[get,post,put,delete,patch].responses
error
0x-response-json-content-type
All responses MUST be application/json.
$.paths.*[get,post,put,delete,patch].responses.*.content
warn
0x-schema-camelcase-properties
Schema properties use camelCase (buyToken, sellAmount, allowanceTarget, blockNumber, gasPrice, totalNetworkFee, liquidityAvailable).
$.components.schemas.*.properties.*~
info
0x-evm-address-pattern
EVM address fields must use the canonical regex `^0x[a-fA-F0-9]{40}$`.
$..properties[?(@property.match(/Token$|Address$|allowanceTarget|taker|recipient/i))]
info
0x-numeric-string-pattern
On-chain integer amounts (buyAmount, sellAmount, gas, value, gasPrice, blockNumber) are returned as decimal strings — enforce string type with a numeric pattern.
$..properties[?(@property.match(/Amount$|^gas$|^value$|^gasPrice$|^blockNumber$/))]
warn
0x-security-scheme-apikey
0x uses an API key passed via the `0x-api-key` request header. The spec SHOULD declare an `apiKey` security scheme.
$.components.securitySchemes
error
0x-get-no-request-body
GET operations MUST NOT have a request body.
$.paths.*.get
warn
0x-post-has-request-body
POST operations (e.g. /gasless/submit) SHOULD define a requestBody.
$.paths.*.post

Spectral Ruleset

Raw ↑
---
# 0x API Spectral Ruleset
# Generated by analysing openapi/0x-api.yaml and openapi/0x-cross-chain.yaml.
# These rules encode the dominant patterns observed across the 0x API surface
# (Swap, Gasless, Cross-Chain, Trade Analytics, Sources). The rules apply
# Spectral 6.x conventions and may be referenced from a `.spectral.yml`
# config via `extends:`.
formats:
  - oas3
rules:
  # --- INFO / METADATA --------------------------------------------------------
  0x-info-title-prefix:
    description: >-
      0x specs are titled "0x API" or "0x <Product> API" — match that pattern.
    message: Info.title MUST start with "0x"
    severity: error
    given: $.info.title
    then:
      function: pattern
      functionOptions:
        match: "^0x( [A-Z][A-Za-z0-9-]+)* API$"

  0x-info-description-required:
    description: Every spec must have an info.description with at least 40 chars.
    message: Info.description is required (>= 40 chars)
    severity: warn
    given: $.info
    then:
      field: description
      function: truthy

  0x-info-version-required:
    description: Spec version MUST be set (e.g. v2 for Swap/Gasless, v1 for Cross-Chain).
    message: Info.version is required
    severity: error
    given: $.info
    then:
      field: version
      function: truthy

  # --- SERVERS ----------------------------------------------------------------
  0x-server-url-canonical:
    description: All 0x APIs are served from https://api.0x.org.
    message: server.url MUST be https://api.0x.org
    severity: error
    given: $.servers[*].url
    then:
      function: pattern
      functionOptions:
        match: "^https://api\\.0x\\.org$"

  # --- PATHS — NAMING CONVENTIONS --------------------------------------------
  0x-paths-kebab-case:
    description: >-
      Path segments use kebab-case (allowance-holder, trade-analytics,
      gasless-approval-tokens, tx-history-beta). Reject snake_case and
      camelCase.
    message: Path segments MUST be kebab-case
    severity: warn
    given: $.paths.*~
    then:
      function: pattern
      functionOptions:
        match: "^(/[a-z0-9-]+|/\\{[A-Za-z]+\\})+$"

  0x-paths-no-trailing-slash:
    description: Paths must not end with a trailing slash.
    message: Path MUST NOT end with '/'
    severity: error
    given: $.paths.*~
    then:
      function: pattern
      functionOptions:
        notMatch: "/$"

  # --- OPERATIONS -------------------------------------------------------------
  0x-operation-operationid-required:
    description: Every operation MUST declare an operationId (used by SDK generators).
    message: operationId is required
    severity: error
    given: $.paths.*[get,post,put,delete,patch]
    then:
      field: operationId
      function: truthy

  0x-operation-operationid-namespaced:
    description: >-
      0x operationIds follow `<api>::<flow>::<verb>` (e.g. swap::permit2::getQuote,
      gasless::submit, crossChain::getQuotes). Enforce double-colon namespacing
      or camelCase verb names.
    message: operationId SHOULD be namespaced (e.g. swap::permit2::getQuote) or camelCase
    severity: warn
    given: $.paths.*[get,post,put,delete,patch].operationId
    then:
      function: pattern
      functionOptions:
        match: "^([a-z][A-Za-z0-9]*)(::[a-z][A-Za-z0-9]*)*$"

  0x-operation-summary-required:
    description: Every operation MUST have a Title Case summary.
    message: Operation summary is required (Title Case)
    severity: error
    given: $.paths.*[get,post,put,delete,patch]
    then:
      field: summary
      function: truthy

  0x-operation-description-required:
    description: Operation description is required and should be at least 30 chars.
    message: Operation description is required
    severity: warn
    given: $.paths.*[get,post,put,delete,patch]
    then:
      field: description
      function: truthy

  0x-operation-tags-required:
    description: >-
      Every operation MUST be tagged with one of: Swap, Gasless, Cross-Chain,
      Trade Analytics, Sources.
    message: Operation MUST have at least one tag
    severity: error
    given: $.paths.*[get,post,put,delete,patch].tags
    then:
      function: length
      functionOptions:
        min: 1

  0x-operation-microcks-extension:
    description: >-
      Operations SHOULD include x-microcks-operation with dispatcher FALLBACK
      for replayable mock generation.
    message: x-microcks-operation extension recommended
    severity: info
    given: $.paths.*[get,post,put,delete,patch]
    then:
      field: x-microcks-operation
      function: truthy

  # --- TAGS -------------------------------------------------------------------
  0x-tags-title-case:
    description: Tag names use Title Case ("Swap", "Cross-Chain", "Trade Analytics").
    message: Tag names MUST be Title Case
    severity: warn
    given: $.paths.*[get,post,put,delete,patch].tags[*]
    then:
      function: pattern
      functionOptions:
        match: "^[A-Z][A-Za-z0-9-]*( [A-Z][A-Za-z0-9-]*)*$"

  # --- PARAMETERS / HEADERS ---------------------------------------------------
  0x-header-api-key-required:
    description: >-
      All 0x API operations require the `0x-api-key` header for authentication.
    message: Every operation MUST require the 0x-api-key header
    severity: error
    given: $.paths.*[get,post,put,delete,patch]
    then:
      field: parameters
      function: schema
      functionOptions:
        schema:
          type: array
          contains:
            type: object
            properties:
              name: { const: "0x-api-key" }
              in: { const: header }
              required: { const: true }
            required: [name, in, required]

  0x-header-version-required:
    description: >-
      Swap, Gasless, Sources, and Trade Analytics operations require the
      `0x-version` header (currently `v2`).
    message: Operation SHOULD require the 0x-version header
    severity: warn
    given: $.paths.*[get,post,put,delete,patch]
    then:
      field: parameters
      function: schema
      functionOptions:
        schema:
          type: array
          contains:
            type: object
            properties:
              name: { const: "0x-version" }
              in: { const: header }
            required: [name, in]

  0x-parameter-camelcase:
    description: >-
      Query and path parameter names use camelCase (chainId, sellToken,
      buyToken, sellAmount, taker, tradeHash, includedSources, excludedSources,
      slippageBps).
    message: Parameter names MUST be camelCase
    severity: warn
    given: "$.paths.*[get,post,put,delete,patch].parameters[?(@.in=='query' || @.in=='path')].name"
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9]*$"

  0x-parameter-description-required:
    description: All parameters MUST be documented.
    message: Parameter description is required
    severity: warn
    given: $.paths.*[get,post,put,delete,patch].parameters[*]
    then:
      field: description
      function: truthy

  0x-chainid-parameter-required:
    description: >-
      Almost every 0x endpoint takes a `chainId` query parameter to route the
      request to the correct EVM chain (or non-EVM virtual chain ID for Solana,
      HyperCore, Tron in the Cross-Chain API).
    message: chainId query parameter expected on chain-scoped operations
    severity: info
    given: "$.paths.*[get,post,put,delete,patch].parameters[?(@.in=='query')].name"
    then:
      function: enumeration
      functionOptions:
        values:
          - chainId
          - originChainId
          - destinationChainId

  # --- RESPONSES --------------------------------------------------------------
  0x-response-200-required:
    description: Every operation MUST document a 200 response.
    message: 200 response is required
    severity: error
    given: $.paths.*[get,post,put,delete,patch].responses
    then:
      field: "200"
      function: truthy

  0x-response-400-recommended:
    description: >-
      Most 0x operations return 400 for INPUT_INVALID / validation failures —
      document it.
    message: 400 response recommended
    severity: warn
    given: $.paths.*[get,post,put,delete,patch].responses
    then:
      field: "400"
      function: truthy

  0x-response-json-content-type:
    description: All responses MUST be application/json.
    message: Response content type MUST be application/json
    severity: error
    given: $.paths.*[get,post,put,delete,patch].responses.*.content
    then:
      field: "application/json"
      function: truthy

  # --- SCHEMAS — PROPERTY NAMING ---------------------------------------------
  0x-schema-camelcase-properties:
    description: >-
      Schema properties use camelCase (buyToken, sellAmount, allowanceTarget,
      blockNumber, gasPrice, totalNetworkFee, liquidityAvailable).
    message: Schema properties MUST be camelCase
    severity: warn
    given: $.components.schemas.*.properties.*~
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9]*$"

  0x-evm-address-pattern:
    description: >-
      EVM address fields must use the canonical regex
      `^0x[a-fA-F0-9]{40}$`.
    message: EVM address fields SHOULD enforce the standard 20-byte hex pattern
    severity: info
    given: $..properties[?(@property.match(/Token$|Address$|allowanceTarget|taker|recipient/i))]
    then:
      field: pattern
      function: truthy

  0x-numeric-string-pattern:
    description: >-
      On-chain integer amounts (buyAmount, sellAmount, gas, value, gasPrice,
      blockNumber) are returned as decimal strings — enforce string type with
      a numeric pattern.
    message: Amount-like fields SHOULD be decimal strings
    severity: info
    given: $..properties[?(@property.match(/Amount$|^gas$|^value$|^gasPrice$|^blockNumber$/))]
    then:
      field: type
      function: enumeration
      functionOptions:
        values: [string]

  # --- SECURITY ---------------------------------------------------------------
  0x-security-scheme-apikey:
    description: >-
      0x uses an API key passed via the `0x-api-key` request header. The spec
      SHOULD declare an `apiKey` security scheme.
    message: "Spec SHOULD declare an `apiKey` security scheme with name '0x-api-key' and `in: header`"
    severity: warn
    given: $.components.securitySchemes
    then:
      function: truthy

  # --- HTTP METHOD CONVENTIONS ------------------------------------------------
  0x-get-no-request-body:
    description: GET operations MUST NOT have a request body.
    message: GET operations MUST NOT define requestBody
    severity: error
    given: $.paths.*.get
    then:
      field: requestBody
      function: falsy

  0x-post-has-request-body:
    description: >-
      POST operations (e.g. /gasless/submit) SHOULD define a requestBody.
    message: POST operations SHOULD define a requestBody
    severity: warn
    given: $.paths.*.post
    then:
      field: requestBody
      function: truthy