TL;DR
The Swagger Petstore is an outdated OpenAPI example that breaks REST fundamentals: inconsistent resource names, verbs in URLs, wrong HTTP status codes, passwords in GET requests, and bare arrays without metadata. Modern PetstoreAPI addresses these flaws with correct RESTful design, RFC 9457 error handling, and production-grade patterns.
Introduction
For over a decade, developers have looked to Swagger Petstore as the go-to OpenAPI example. But its design is flawed—leading countless APIs to inherit anti-patterns, security risks, and inconsistent conventions. Relying on it is like learning to drive with swapped brake and gas pedals: you’ll learn, but you’ll learn badly.
These issues propagate into production code, causing inconsistent naming, misused HTTP methods, and security vulnerabilities. Code reviews often overlook these problems because “that’s how Petstore does it.”
💡 Tip: Apidog helps you validate API design against REST principles, test endpoint behavior, and catch design flaws before they reach production. Import OpenAPI specs, run automated tests, and enforce REST conventions.
This guide breaks down what's wrong with Swagger Petstore, how it impacts your API, and how Modern PetstoreAPI solves these issues. You’ll see practical comparisons, actionable fixes, and how to test your API with Apidog.
The Swagger Petstore Legacy Problem
Swagger Petstore was created in 2011 to show how to write a Swagger (OpenAPI) spec—not as a REST API design reference.
Why It Became the De Facto Standard
Developers start with official examples. Swagger Petstore appears in docs, tutorials, and code generators. Many assume “official example = best practice” and copy its patterns into real APIs.
The Cost of Bad Examples
Poor examples lead to:
- Juniors learning anti-patterns (without realizing it)
- Code generators perpetuating issues (flawed SDKs)
- Docs tools showing bad patterns (Swagger UI defaults)
- Companies building bad APIs (assuming it’s “best practice”)
Swagger Petstore’s impact is massive—so its design flaws matter.
Critical REST Violations in Swagger Petstore
Let’s break down the main violations and how to fix them.
1. Inconsistent Resource Naming (Plural vs Singular)
Violation:
GET /pet/{petId} # Singular
GET /store/inventory # Plural
POST /pet # Singular
GET /user/{username} # Singular
Why It’s Wrong:
REST collections should use plural nouns (e.g., /pets). Inconsistency makes it unclear whether you’re dealing with a collection or resource.
Modern PetstoreAPI Fix:
GET /pets/{petId} # Always plural
GET /stores/inventory # Consistent
POST /pets # Plural for collection
GET /users/{username} # Plural everywhere
See the REST API documentation for the full structure.
2. Action Verbs in URLs
Violation:
GET /pet/findByStatus?status=available
GET /pet/findByTags?tags=tag1,tag2
GET /user/login?username=john&password=secret
GET /user/logout
Why It’s Wrong:
RESTful URLs should represent resources (nouns), not actions (verbs). HTTP methods are the verbs. Verbs in paths indicate RPC thinking, not REST.
Modern PetstoreAPI Fix:
GET /pets?status=AVAILABLE # Filter via query
GET /pets?tags=tag1,tag2 # Query parameter filtering
POST /auth/login # Separate auth resource
POST /auth/logout # RESTful auth endpoints
See the authentication guide for proper patterns.
3. Wrong HTTP Status Codes
Violation:
POST /pet
# Response: 200 OK (should be 201 Created)
DELETE /pet/{petId}
# Response: 200 OK (should be 204 No Content)
# Body: { "message": "Pet deleted" }
Why It’s Wrong:
-
200 OKis for successful resource retrieval. -
201 Createdis for successful creation (with aLocationheader). -
204 No Contentis for successful deletion (with no body).
Modern PetstoreAPI Fix:
POST /pets
# Response: 201 Created
# Location: /pets/{id}
{
"id": "...",
"name": "Fluffy",
"status": "AVAILABLE"
}
DELETE /pets/{petId}
# Response: 204 No Content
# (no body)
See the HTTP status codes guide for mapping.
4. Bare Arrays Without Metadata
Violation:
GET /pet/findByStatus?status=available
# Response: 200 OK
[
{"id": 1, "name": "Fluffy"},
{"id": 2, "name": "Buddy"}
]
Why It’s Wrong:
- No pagination info
- No extensibility for metadata or links
- No HATEOAS
- JSON Hijacking risk
Modern PetstoreAPI Fix:
{
"data": [
{"id": "...", "name": "Fluffy"},
{"id": "...", "name": "Buddy"}
],
"pagination": {
"page": 1,
"limit": 20,
"totalItems": 45,
"totalPages": 3
},
"links": {
"self": "/pets?status=AVAILABLE&page=1",
"next": "/pets?status=AVAILABLE&page=2",
"last": "/pets?status=AVAILABLE&page=3"
}
}
See the pagination guide for implementation.
5. Missing Error Standards
Violation:
{
"code": 400,
"message": "Invalid input"
}
Why It’s Wrong:
- No error type identifier
- No field-level validation
- No machine-readable codes
- Ignores RFC 9457 (“Problem Details”)
Modern PetstoreAPI Fix:
{
"type": "https://petstoreapi.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "Request validation failed",
"instance": "/pets",
"errors": [
{
"field": "name",
"message": "Name is required",
"code": "REQUIRED_FIELD"
},
{
"field": "status",
"message": "Status must be one of: AVAILABLE, PENDING, SOLD",
"code": "INVALID_ENUM"
}
]
}
See the error handling guide for complete format.
Security Disasters in the Old Design
Swagger Petstore has major security vulnerabilities.
GET Request with Passwords
Violation:
GET /user/login?username=john&password=secret123
Why It’s a Disaster:
- Passwords appear in browser history, server logs, referrer headers, proxies, bookmarks.
- Never put credentials in URLs.
Modern PetstoreAPI Fix:
POST /auth/login
Content-Type: application/json
{
"username": "john",
"password": "secret123"
}
# Response: 200 OK
{
"accessToken": "...",
"refreshToken": "...",
"expiresIn": 3600
}
See the authentication guide for OAuth 2.0/JWT details.
API Keys in Query Parameters
Violation:
GET /pet/123?api_key=abc123secret
Why It’s Wrong:
API keys in query params are logged, cached, and exposed like passwords.
Modern PetstoreAPI Fix:
GET /pets/{petId}
Authorization: Bearer <token>
See the security guide for proper authentication.
How Modern PetstoreAPI Fixes These Issues
Modern PetstoreAPI is a reference for robust REST API design.
Production-Ready REST Design
-
Consistent plural naming:
/pets,/orders,/users - Resource-oriented URLs: nouns only
-
Accurate HTTP status codes:
201,204, proper errors - Wrapped collections: with pagination and metadata
- RFC 9457 errors: structured, field-level validation
Modern Standards
- OpenAPI 3.2
- RFC 9457 (Problem Details)
-
IETF Rate Limiting (
RateLimit-*headers) - ISO 8601 dates
- UUIDv7 IDs
Multi-Protocol Support
Modern PetstoreAPI supports:
- REST (OpenAPI 3.2)
- GraphQL
- gRPC
- WebSocket
- SSE
- MQTT
- Webhooks
- MCP
See the protocols guide for details.
Real Business Logic
Includes:
- Payment processing
- Inventory
- Orders
- Webhooks
- AI-powered recommendations
- Image upload/processing
See the API documentation for all features.
Testing REST API Design with Apidog
Apidog lets you validate REST API design and catch issues early.
Import and Validate OpenAPI Specs
# Steps:
1. Open Apidog
2. Click "Import" → "OpenAPI"
3. Enter: https://petstoreapi.com/openapi.json
4. Apidog validates the spec and creates test cases
Apidog will flag:
- Inconsistent resource naming
- Missing HTTP status codes
- Invalid response structures
- Security/authentication issues
Test REST Principles
Resource Names Are Plural
// Apidog test script
pm.test("Endpoint uses plural resource name", function() {
const url = pm.request.url.toString();
pm.expect(url).to.match(/\/pets\/|\/orders\/|\/users\//);
pm.expect(url).to.not.match(/\/pet\/|\/order\/|\/user\//);
});
Correct Status Codes
pm.test("POST returns 201 Created", function() {
if (pm.request.method === "POST") {
pm.response.to.have.status(201);
pm.response.to.have.header("Location");
}
});
pm.test("DELETE returns 204 No Content", function() {
if (pm.request.method === "DELETE") {
pm.response.to.have.status(204);
pm.expect(pm.response.text()).to.be.empty;
}
});
Collections Have Metadata
pm.test("Collection response includes pagination", function() {
const response = pm.response.json();
pm.expect(response).to.have.property("data");
pm.expect(response).to.have.property("pagination");
pm.expect(response.pagination).to.have.property("page");
pm.expect(response.pagination).to.have.property("totalItems");
});
Compare Old vs New Petstore
- Import Swagger Petstore:
https://petstore.swagger.io/v2/swagger.json - Import Modern PetstoreAPI:
https://petstoreapi.com/openapi.json - Run automated tests on both
- Compare results side-by-side
Apidog will highlight Swagger Petstore’s design violations and Modern PetstoreAPI’s fixes.
Migration Guide: Old Petstore to Modern Design
Migrating from Swagger Petstore? Follow these actionable steps.
Step 1: Fix Resource Names
Before:
GET /pet/{petId}
POST /pet
DELETE /pet/{petId}
After:
GET /pets/{petId}
POST /pets
DELETE /pets/{petId}
Strategy:
- Support both endpoints during transition
- Add deprecation warnings to old endpoints
- Update docs to show new endpoints
- Remove old endpoints after 6 months
Step 2: Remove Action Verbs
Before:
GET /pet/findByStatus?status=available
GET /pet/findByTags?tags=tag1,tag2
After:
GET /pets?status=AVAILABLE
GET /pets?tags=tag1,tag2
Strategy:
- Redirect old endpoints to new (301 Moved Permanently)
- Update client SDKs
- Add query parameter validation
Step 3: Fix HTTP Status Codes
Before:
POST /pet → 200 OK
DELETE /pet/{petId} → 200 OK with body
After:
POST /pets → 201 Created with Location header
DELETE /pets/{petId} → 204 No Content (no body)
Strategy:
- Breaking change: version your API (e.g., v2)
- Document changes clearly
- Provide migration timeline
Step 4: Wrap Collections
Before:
[
{"id": 1, "name": "Fluffy"},
{"id": 2, "name": "Buddy"}
]
After:
{
"data": [...],
"pagination": {...},
"links": {...}
}
Strategy:
- Breaking change: create v2 endpoints with wrapped responses
- Deprecate v1 endpoints
- Update client code
Step 5: Implement RFC 9457 Errors
Before:
{
"code": 400,
"message": "Invalid input"
}
After:
{
"type": "https://petstoreapi.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "Request validation failed",
"errors": [...]
}
Strategy:
- Add
Content-Type: application/problem+jsonheader - Support both formats during transition
- Update client error handling
- Remove old format after migration
Real-World Impact of Bad API Design
Developer Confusion
Violating REST principles causes:
- Guesswork on HTTP methods
- Inconsistent naming headaches
- Unexpected status codes
- Error handling confusion
Cost: Hours lost per integration.
Client Bugs
Leads to:
- Parsing errors from inconsistent responses
- Auth failures from wrong methods
- Pagination bugs from missing metadata
- Poor error handling
Cost: Production incidents and customer issues.
Security Vulnerabilities
Design flaws lead to:
- Passwords and keys in logs/history
- Missing auth on sensitive endpoints
- Error messages leaking system info
Cost: Data breaches and compliance risks.
Technical Debt
Bad patterns compound:
- New devs copy anti-patterns
- Code generators spread flaws
- Docs show incorrect examples
Cost: Long-term maintenance pain.
Conclusion
Swagger Petstore was a simple OpenAPI demo, but its REST violations and anti-patterns are no longer acceptable. Modern PetstoreAPI is the reference you should follow for robust RESTful APIs: proper naming, modern standards, multi-protocol support, production-ready features.
Test your APIs with Apidog to catch design errors early. Import your OpenAPI specs, run automated tests, and ensure your APIs meet REST principles before launch.
Next Steps:
- Explore Modern PetstoreAPI documentation
- Compare your API to Modern PetstoreAPI patterns
- Import your OpenAPI spec into Apidog for validation
- Fix REST violations using the migration guide above
- Adopt RFC 9457 for error handling
The era of bad API examples is over. Build APIs the right way with Modern PetstoreAPI.
FAQ
Why did Swagger create a bad example?
Swagger Petstore was a 2011 demo for the Swagger spec, not a REST API reference. Unfortunately, it became the default example, and its flaws were copied everywhere.
Should I stop using Swagger Petstore?
Yes, for REST API design. Use Modern PetstoreAPI instead—it demonstrates correct REST principles, standards, and production patterns.
Is Modern PetstoreAPI production-ready?
Yes. Modern PetstoreAPI includes realistic business logic, proper error handling, authentication, rate limiting, and security features. Use it as a template or direct reference.
How do I test if my API follows REST principles?
Import your OpenAPI spec into Apidog and run automated tests. It validates naming, status codes, response structures, and security.
What’s the biggest mistake in Swagger Petstore?
Using GET /user/login with passwords in the URL—a critical security flaw. Always use POST with JSON bodies for authentication.
Can I migrate from Swagger Petstore patterns gradually?
Yes. Support both old and new endpoints during transition. Add deprecation warnings, update docs, monitor usage, and remove old endpoints after client migration (6–12 months).
Does Modern PetstoreAPI support GraphQL and gRPC?
Yes. Modern PetstoreAPI supports REST, GraphQL, gRPC, WebSocket, SSE, MQTT, Webhooks, and MCP. See the protocols guide for details.
How do I convince my team to fix our API design?
Show the real costs: developer confusion, client bugs, security risks, and technical debt. Use Apidog to demonstrate issues in your current API and compare with Modern PetstoreAPI.
Top comments (0)