---
title: "APIs.guru directory API: spec vs live"
date: 2026-10-30
canonical: https://apidrifter.com/research/public-api-spec-drift-2026-11/apis-guru/
part_of: https://apidrifter.com/research/public-api-spec-drift-2026-11/
---

# APIs.guru directory API: spec vs live

Part of [We checked 13 public APIs against their own OpenAPI specs. 9 had hard mismatches.](https://apidrifter.com/research/public-api-spec-drift-2026-11/).

## Summary

- Spec: https://api.apis.guru/v2/openapi.yaml (OpenAPI 3)
- Base URL: `https://api.apis.guru/v2`
- Run: 2026-10-30, read-only GET requests, no credentials
- Coverage: 7 operations in the spec, 6 requests sent, 6 successful, 6 operations observed
- Hard violations: 13 distinct schema locations
- Reviewer note: Confirmed: GET /specs/{provider}/{api}.json returns the OpenAPI document itself; the spec documents the API entry object (preferred, versions).

## Hard violations (13)

A typed client generated from the spec would break on these.

- `response-forbidden-property` (hard, breaking) at `GET /specs/{provider}/{api}.json > response 200 > application/json > /externalDocs`
  - response body at /externalDocs: property "externalDocs" is not allowed
  - Request: `GET /specs/apis.guru/2.2.0.json -> 200 application/json`
  - Actual: `"externalDocs"`
  - If the spec is the source of truth: Stop returning "externalDocs" from GET /specs/{provider}/{api}.json; the spec forbids unknown properties here.
  - If the implementation is the source of truth: Add "externalDocs" to paths["/specs/{provider}/{api}.json"].get.responses["200"].content["application/json"].schema.properties or allow additionalProperties.
- `response-forbidden-property` (hard, breaking) at `GET /specs/{provider}/{api}.json > response 200 > application/json > /info`
  - response body at /info: property "info" is not allowed
  - Request: `GET /specs/apis.guru/2.2.0.json -> 200 application/json`
  - Actual: `"info"`
  - If the spec is the source of truth: Stop returning "info" from GET /specs/{provider}/{api}.json; the spec forbids unknown properties here.
  - If the implementation is the source of truth: Add "info" to paths["/specs/{provider}/{api}.json"].get.responses["200"].content["application/json"].schema.properties or allow additionalProperties.
- `response-forbidden-property` (hard, breaking) at `GET /specs/{provider}/{api}.json > response 200 > application/json > /link`
  - response body at /link: property "link" is not allowed
  - Request: `GET /specs/apis.guru/2.2.0.json -> 200 application/json`
  - Actual: `"link"`
  - If the spec is the source of truth: Stop returning "link" from GET /specs/{provider}/{api}.json; the spec forbids unknown properties here.
  - If the implementation is the source of truth: Add "link" to paths["/specs/{provider}/{api}.json"].get.responses["200"].content["application/json"].schema.properties or allow additionalProperties.
- `response-forbidden-property` (hard, breaking) at `GET /specs/{provider}/{api}.json > response 200 > application/json > /openapiVer`
  - response body at /openapiVer: property "openapiVer" is not allowed
  - Request: `GET /specs/apis.guru/2.2.0.json -> 200 application/json`
  - Actual: `"openapiVer"`
  - If the spec is the source of truth: Stop returning "openapiVer" from GET /specs/{provider}/{api}.json; the spec forbids unknown properties here.
  - If the implementation is the source of truth: Add "openapiVer" to paths["/specs/{provider}/{api}.json"].get.responses["200"].content["application/json"].schema.properties or allow additionalProperties.
- `response-missing-required-property` (hard, breaking) at `GET /specs/{provider}/{api}.json > response 200 > application/json > /preferred`
  - response body at /preferred: required property "preferred" is missing
  - Request: `GET /specs/apis.guru/2.2.0.json -> 200 application/json`
  - Expected: `"preferred"`
  - If the spec is the source of truth: Include "preferred" in the 200 response of GET /specs/{provider}/{api}.json.
  - If the implementation is the source of truth: Remove "preferred" from required at paths["/specs/{provider}/{api}.json"].get.responses["200"].content["application/json"].schema.
- `response-forbidden-property` (hard, breaking) at `GET /specs/{provider}/{api}.json > response 200 > application/json > /swaggerUrl`
  - response body at /swaggerUrl: property "swaggerUrl" is not allowed
  - Request: `GET /specs/apis.guru/2.2.0.json -> 200 application/json`
  - Actual: `"swaggerUrl"`
  - If the spec is the source of truth: Stop returning "swaggerUrl" from GET /specs/{provider}/{api}.json; the spec forbids unknown properties here.
  - If the implementation is the source of truth: Add "swaggerUrl" to paths["/specs/{provider}/{api}.json"].get.responses["200"].content["application/json"].schema.properties or allow additionalProperties.
- `response-forbidden-property` (hard, breaking) at `GET /specs/{provider}/{api}.json > response 200 > application/json > /swaggerYamlUrl`
  - response body at /swaggerYamlUrl: property "swaggerYamlUrl" is not allowed
  - Request: `GET /specs/apis.guru/2.2.0.json -> 200 application/json`
  - Actual: `"swaggerYamlUrl"`
  - If the spec is the source of truth: Stop returning "swaggerYamlUrl" from GET /specs/{provider}/{api}.json; the spec forbids unknown properties here.
  - If the implementation is the source of truth: Add "swaggerYamlUrl" to paths["/specs/{provider}/{api}.json"].get.responses["200"].content["application/json"].schema.properties or allow additionalProperties.
- `response-forbidden-property` (hard, breaking) at `GET /specs/{provider}/{api}.json > response 200 > application/json > /updated`
  - response body at /updated: property "updated" is not allowed
  - Request: `GET /specs/apis.guru/2.2.0.json -> 200 application/json`
  - Actual: `"updated"`
  - If the spec is the source of truth: Stop returning "updated" from GET /specs/{provider}/{api}.json; the spec forbids unknown properties here.
  - If the implementation is the source of truth: Add "updated" to paths["/specs/{provider}/{api}.json"].get.responses["200"].content["application/json"].schema.properties or allow additionalProperties.
- `response-missing-required-property` (hard, breaking) at `GET /specs/{provider}/{api}.json > response 200 > application/json > /versions`
  - response body at /versions: required property "versions" is missing
  - Request: `GET /specs/apis.guru/2.2.0.json -> 200 application/json`
  - Expected: `"versions"`
  - If the spec is the source of truth: Include "versions" in the 200 response of GET /specs/{provider}/{api}.json.
  - If the implementation is the source of truth: Remove "versions" from required at paths["/specs/{provider}/{api}.json"].get.responses["200"].content["application/json"].schema.
- `response-missing-required-property` (hard, breaking) at `GET /{provider}.json > response 200 > application/json > /apis/added`
  - response body at /apis/added: required property "added" is missing
  - Request: `GET /apis.guru.json -> 200 application/json`
  - Expected: `"added"`
  - If the spec is the source of truth: Include "added" in the 200 response of GET /{provider}.json.
  - If the implementation is the source of truth: Remove "added" from required at paths["/{provider}.json"].get.responses["200"].content["application/json"].schema.properties["apis"].
- `response-forbidden-property` (hard, breaking) at `GET /{provider}.json > response 200 > application/json > /apis/apis.guru`
  - response body at /apis/apis.guru: property "apis.guru" is not allowed
  - Request: `GET /apis.guru.json -> 200 application/json`
  - Actual: `"apis.guru"`
  - If the spec is the source of truth: Stop returning "apis.guru" from GET /{provider}.json; the spec forbids unknown properties here.
  - If the implementation is the source of truth: Add "apis.guru" to paths["/{provider}.json"].get.responses["200"].content["application/json"].schema.properties["apis"].properties or allow additionalProperties.
- `response-missing-required-property` (hard, breaking) at `GET /{provider}.json > response 200 > application/json > /apis/preferred`
  - response body at /apis/preferred: required property "preferred" is missing
  - Request: `GET /apis.guru.json -> 200 application/json`
  - Expected: `"preferred"`
  - If the spec is the source of truth: Include "preferred" in the 200 response of GET /{provider}.json.
  - If the implementation is the source of truth: Remove "preferred" from required at paths["/{provider}.json"].get.responses["200"].content["application/json"].schema.properties["apis"].
- `response-missing-required-property` (hard, breaking) at `GET /{provider}.json > response 200 > application/json > /apis/versions`
  - response body at /apis/versions: required property "versions" is missing
  - Request: `GET /apis.guru.json -> 200 application/json`
  - Expected: `"versions"`
  - If the spec is the source of truth: Include "versions" in the 200 response of GET /{provider}.json.
  - If the implementation is the source of truth: Remove "versions" from required at paths["/{provider}.json"].get.responses["200"].content["application/json"].schema.properties["apis"].

## Reproduce

```sh
curl -s -H 'Accept: application/json' 'https://api.apis.guru/v2/specs/apis.guru/2.2.0.json'
```

## Data

- Findings: https://github.com/apidrifter/apidrifter/tree/main/tools/survey/results/apis-guru.findings.json
- Requests sent: https://github.com/apidrifter/apidrifter/tree/main/tools/survey/results/apis-guru.observations.json
- Tool: https://apidrifter.com/docs/cli/ (reproduce with apidrifter run; target definition in tools/survey/targets.json)
