---
title: "Swagger Petstore (reference demo): spec vs live"
date: 2026-10-30
canonical: https://apidrifter.com/research/public-api-spec-drift-2026-11/petstore/
part_of: https://apidrifter.com/research/public-api-spec-drift-2026-11/
---

# Swagger Petstore (reference demo): 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://petstore3.swagger.io/api/v3/openapi.json (OpenAPI 3)
- Base URL: `https://petstore3.swagger.io/api/v3`
- Run: 2026-10-30, read-only GET requests, no credentials
- Coverage: 19 operations in the spec, 8 requests sent, 6 successful, 8 operations observed
- Hard violations: 1 distinct schema locations
- Reviewer note: Confirmed: GET /user/login returns a plain-text session string under application/json.

## Hard violations (1)

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

- `response-body-not-json` (hard, warning) at `GET /user/login > response 200 > application/json`
  - the 200 response is documented as "application/json" but the body is not valid JSON
  - Request: `GET /user/login -> 200 application/json`
  - If the spec is the source of truth: Return valid JSON from GET /user/login for the 200 response.
  - If the implementation is the source of truth: Change the media type at paths["/user/login"].get.responses["200"].content to what is actually returned.

## Reproduce

```sh
curl -s -H 'Accept: application/json' 'https://petstore3.swagger.io/api/v3/user/login'
```

## Data

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