TL;DR
The Swagger Petstore violates fundamental REST principles: it uses singular resource names inconsistently, includes action verbs in URLs, returns wrong HTTP status codes, exposes passwords in GET requests, and returns bare arrays without metadata. Modern PetstoreAPI fixes all these issues with proper RESTful design, RFC 9457 error handling, and production-ready patterns.
Introduction
For over a decade, the Swagger Petstore has been the default example for learning OpenAPI. Millions of developers have studied it, copied its patterns, and built production APIs based on its design. There’s one problem: it teaches you to build bad APIs.
The Swagger Petstore violates basic REST principles, includes security vulnerabilities, and demonstrates anti-patterns that harm production systems. It’s like learning to drive with a car that has the brake and gas pedals swapped—you’ll learn, but you’ll learn wrong.
The damage is real. Developers who learned from Swagger Petstore carry these anti-patterns into production code. APIs get built with inconsistent naming, wrong HTTP methods, and security holes. Code reviews miss these issues because “that’s how Petstore does it.”
In this guide, you’ll learn exactly what’s wrong with Swagger Petstore, why these issues matter, and how Modern PetstoreAPI fixes them with production-ready patterns. You’ll see side-by-side comparisons, understand the impact of each violation, and discover how to test your APIs properly with Apidog.
The Swagger Petstore Legacy Problem
The Swagger Petstore was created in 2011 as a simple example for the Swagger specification (now OpenAPI). It served its purpose: demonstrate how to write an OpenAPI spec. But it was never meant to be a reference for REST API design.
Why It Became the De Facto Standard
When developers learn OpenAPI, they start with the official example. The Swagger Petstore is that example. It’s in the documentation, tutorials, and code generators. If you’ve used Swagger UI or Swagger Codegen, you’ve seen it.
The problem: developers assume “official example = best practice.” They copy the patterns without questioning them. API design courses use it as a teaching tool. Companies build internal APIs following its structure.
The Cost of Bad Examples
Bad examples compound over time:
- Junior developers learn anti-patterns - They don’t know these are mistakes
- Code generators perpetuate the issues - Generated SDKs inherit the flaws
- Documentation tools show bad examples - Swagger UI displays the Petstore by default
- Companies build production APIs this way - “If it’s good enough for Swagger…”
The Swagger Petstore has probably influenced more API designs than any other example in history. That’s why its flaws matter.
Critical REST Violations in Swagger Petstore
Let’s examine the specific REST violations in Swagger Petstore and why they’re wrong.
1. Inconsistent Resource Naming (Plural vs Singular)
The Violation:
GET /pet/{petId} ← Singular
GET /store/inventory ← Plural
POST /pet ← Singular
GET /user/{username} ← Singular
Why It’s Wrong:
REST resources represent collections. A collection is plural. When you access /pets, you’re accessing the pets collection. When you access /pets/123, you’re accessing item 123 in the pets collection.
Mixing singular and plural breaks this mental model. Is /pet/123 accessing the pet collection or a single pet resource? The inconsistency creates confusion.
Modern PetstoreAPI Fix:
GET /pets/{petId} ← Always plural
GET /stores/inventory ← Consistent
POST /pets ← Plural for collection
GET /users/{username} ← Plural everywhere
Modern PetstoreAPI uses plural resource names consistently across all endpoints. Check the REST API documentation for the complete endpoint structure.
2. Action Verbs in URLs
The 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:
REST URLs should represent resources (nouns), not actions (verbs). The HTTP method is the verb. GET /pets means “get the pets resource.” Adding findByStatus is redundant—that’s what query parameters are for.
Action verbs in URLs indicate you’re thinking in RPC (Remote Procedure Call) terms, not REST terms. You’re exposing implementation details instead of resources.
Modern PetstoreAPI Fix:
GET /pets?status=AVAILABLE ← Resource + filter
GET /pets?tags=tag1,tag2 ← Query parameters for filtering
POST /auth/login ← Separate auth resource
POST /auth/logout ← RESTful auth endpoints
The Modern PetstoreAPI uses query parameters for filtering and separate authentication resources. See the authentication guide for proper auth patterns.
3. Wrong HTTP Status Codes
The Violation:
POST /pet
Response: 200 OK ← Should be 201 Created
DELETE /pet/{petId}
Response: 200 OK ← Should be 204 No Content
{
"message": "Pet deleted"
}
Why It’s Wrong:
HTTP status codes have specific meanings:
200 OKmeans “request succeeded, here’s the resource”201 Createdmeans “resource created, here’s where to find it”204 No Contentmeans “request succeeded, no body to return”
Using 200 for everything breaks HTTP semantics. Clients can’t distinguish between “resource retrieved” and “resource created.” Returning a body with DELETE wastes bandwidth—the client doesn’t need confirmation text.
Modern PetstoreAPI Fix:
POST /pets
Response: 201 Created
Location: /pets/019b4132-70aa-764f-b315-e2803d882a24
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"status": "AVAILABLE"
}
DELETE /pets/{petId}
Response: 204 No Content
(no body)
Modern PetstoreAPI uses correct HTTP status codes and includes Location headers for created resources. Check the HTTP status codes guide for the complete mapping.
4. Bare Arrays Without Metadata
The Violation:
GET /pet/findByStatus?status=available
Response: 200 OK
[
{"id": 1, "name": "Fluffy"},
{"id": 2, "name": "Buddy"}
]
Why It’s Wrong:
Returning bare arrays creates problems:
- No pagination metadata - How many total items? What page am I on?
- No extensibility - Can’t add metadata without breaking clients
- No HATEOAS links - Can’t include navigation links
- JSON Hijacking risk - Bare arrays are vulnerable to certain attacks
Modern PetstoreAPI Fix:
GET /pets?status=AVAILABLE
Response: 200 OK
{
"data": [
{"id": "019b4132-70aa-764f-b315-e2803d882a24", "name": "Fluffy"},
{"id": "019b4127-54d5-76d9-b626-0d4c7bfce5b6", "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"
}
}
Modern PetstoreAPI wraps all collections in objects with metadata and HATEOAS links. See the pagination guide for implementation details.
5. Missing Error Standards
The Violation:
Response: 400 Bad Request
{
"code": 400,
"message": "Invalid input"
}
Why It’s Wrong:
This error format is non-standard and provides minimal information:
- No error type identifier
- No field-level validation errors
- No machine-readable error codes
- Doesn’t follow RFC 9457 (Problem Details)
Modern PetstoreAPI Fix:
Response: 400 Bad Request
Content-Type: application/problem+json
{
"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"
}
]
}
Modern PetstoreAPI uses RFC 9457 Problem Details for all errors. See the error handling guide for the complete error format.
Security Disasters in the Old Design
Beyond REST violations, Swagger Petstore has serious security issues.
GET Request with Passwords
The Violation:
GET /user/login?username=john&password=secret123
Why It’s a Disaster:
Passwords in GET requests appear in:
- Browser history - Anyone with access to the browser sees the password
- Server logs - Web servers log full URLs including query parameters
- Referrer headers - If the user clicks a link after login, the next site sees the password
- Proxy logs - Corporate proxies log all URLs
- Browser bookmarks - Users might bookmark the login URL
This is a critical security vulnerability. Passwords should never be in URLs.
Modern PetstoreAPI Fix:
POST /auth/login
Content-Type: application/json
{
"username": "john",
"password": "secret123"
}
Response: 200 OK
{
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc...",
"expiresIn": 3600
}
Modern PetstoreAPI uses POST for authentication with JSON bodies. Passwords never appear in URLs. See the authentication guide for OAuth 2.0 and JWT patterns.
API Keys in Query Parameters
The Violation:
GET /pet/123?api_key=abc123secret
Why It’s Wrong:
API keys in query parameters have the same problems as passwords in URLs:
- Logged everywhere
- Visible in browser history
- Sent in referrer headers
- Cached by proxies
Modern PetstoreAPI Fix:
GET /pets/019b4132-70aa-764f-b315-e2803d882a24
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Modern PetstoreAPI uses standard Authorization headers for API keys and tokens. See the security guide for authentication patterns.
How Modern PetstoreAPI Fixes These Issues
Modern PetstoreAPI was built from scratch to demonstrate proper REST API design. Here’s what makes it different:
Production-Ready REST Design
- Consistent plural resource names -
/pets,/orders,/users - Resource-oriented URLs - No action verbs, only nouns
- Correct HTTP status codes - 201 for creation, 204 for deletion, proper error codes
- Collection wrappers - All lists include pagination and metadata
- RFC 9457 errors - Standard error format with field-level validation
Modern Standards
- OpenAPI 3.2 - Latest specification with all features
- RFC 9457 - Problem Details for HTTP APIs
- IETF Rate Limiting - Standard
RateLimit-*headers - ISO 8601 - Proper date/time formats
- UUIDv7 - Sortable unique identifiers
Multi-Protocol Support
Unlike Swagger Petstore (REST only), Modern PetstoreAPI supports:
- REST (OpenAPI 3.2)
- GraphQL
- gRPC
- WebSocket
- Server-Sent Events (SSE)
- MQTT
- Webhooks
- Model Context Protocol (MCP)
See the protocols guide for implementation details.
Real Business Logic
Modern PetstoreAPI includes realistic features:
- Payment processing
- Inventory management
- Order fulfillment
- Webhook notifications
- AI-powered pet recommendations
- Image upload and processing
Check the API documentation for the complete feature set.
Testing REST API Design with Apidog
Apidog helps you validate REST API design and catch violations before they reach production.
Import and Validate OpenAPI Specs
# Import Modern PetstoreAPI spec
1. Open Apidog
2. Click "Import" → "OpenAPI"
3. Enter: https://petstoreapi.com/openapi.json
4. Apidog validates the spec and creates test cases
Apidog automatically detects:
- Inconsistent resource naming
- Missing HTTP status codes
- Invalid response structures
- Security issues in authentication
Test REST Principles
Create test cases that verify REST compliance:
Test: 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\//);
});
Test: 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;
}
});
Test: 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 both specs into Apidog and run side-by-side comparisons:
- 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 to see the differences
Apidog will highlight the design violations in Swagger Petstore and show how Modern PetstoreAPI fixes them.
Migration Guide: Old Petstore to Modern Design
If you built an API based on Swagger Petstore, here’s how to migrate to proper REST design:
Step 1: Fix Resource Names
Before:
GET /pet/{petId}
POST /pet
DELETE /pet/{petId}
After:
GET /pets/{petId}
POST /pets
DELETE /pets/{petId}
Migration Strategy:
- Support both endpoints during transition
- Add deprecation warnings to old endpoints
- Update documentation to show new endpoints
- Monitor usage and 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
Migration Strategy:
- Redirect old endpoints to new ones with 301 Moved Permanently
- Update client SDKs to use new endpoints
- 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)
Migration Strategy:
- This is a breaking change for clients checking status codes
- Version your API (v2) with correct status codes
- Document the changes clearly
- Provide migration timeline
Step 4: Wrap Collections
Before:
[
{"id": 1, "name": "Fluffy"},
{"id": 2, "name": "Buddy"}
]
After:
{
"data": [...],
"pagination": {...},
"links": {...}
}
Migration Strategy:
- This is a breaking change
- Create v2 endpoints with wrapped responses
- Deprecate v1 endpoints
- Update client code to handle new structure
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": [...]
}
Migration Strategy:
- Add
Content-Type: application/problem+jsonheader - Include both old and new error formats during transition
- Update client error handling
- Remove old format after migration period
Real-World Impact of Bad API Design
Bad API design has real costs:
Developer Confusion
When APIs violate REST principles, developers waste time:
- Guessing which HTTP method to use
- Figuring out inconsistent naming patterns
- Debugging unexpected status codes
- Handling errors without proper structure
Cost: Hours of developer time per integration
Client Bugs
Inconsistent APIs lead to client-side bugs:
- Parsing errors from unexpected response structures
- Authentication failures from wrong HTTP methods
- Pagination issues from missing metadata
- Error handling failures from non-standard formats
Cost: Production incidents and customer impact
Security Vulnerabilities
Design flaws create security risks:
- Passwords in URLs get logged
- API keys in query parameters get cached
- Missing authentication on sensitive endpoints
- Improper error messages leak system information
Cost: Data breaches and compliance violations
Technical Debt
Bad examples compound over time:
- New developers learn anti-patterns
- Code generators produce flawed SDKs
- Documentation shows incorrect examples
- Companies build new APIs with same mistakes
Cost: Long-term maintenance burden
Conclusion
The Swagger Petstore served its purpose as a simple OpenAPI example, but it’s time to move on. Its REST violations, security issues, and anti-patterns have influenced too many production APIs.
Modern PetstoreAPI provides the reference implementation the industry needs: proper REST design, modern standards, multi-protocol support, and production-ready patterns. Use it as your learning resource and reference for API design.
Test your APIs with Apidog to catch design violations early. Import your OpenAPI specs, run automated tests, and ensure your APIs follow REST principles before they reach production.
Next Steps:
- Explore Modern PetstoreAPI documentation
- Compare your API design 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?
The Swagger Petstore was created in 2011 as a simple demonstration of the Swagger specification. It wasn’t meant to be a REST API design reference. The problem is that it became the de facto standard example, and its flaws were copied by millions of developers.
Should I stop using Swagger Petstore?
Yes, for learning REST API design. Use Modern PetstoreAPI instead. It demonstrates proper REST principles, modern standards, and production-ready patterns. The old Petstore teaches anti-patterns that harm production systems.
Is Modern PetstoreAPI production-ready?
Yes. Modern PetstoreAPI includes realistic business logic, proper error handling, authentication, rate limiting, and security features. You can deploy it with minimal modifications or use it as a reference for your own API design.
How do I test if my API follows REST principles?
Import your OpenAPI spec into Apidog and run automated tests. Apidog validates resource naming, HTTP status codes, response structures, and security patterns. You can also compare your API side-by-side with Modern PetstoreAPI.
What’s the biggest mistake in Swagger Petstore?
Using GET /user/login with passwords in query parameters. This exposes passwords in browser history, server logs, and referrer headers—a critical security vulnerability. Always use POST with JSON bodies for authentication.
Can I migrate from Swagger Petstore patterns gradually?
Yes. Support both old and new endpoints during a transition period. Add deprecation warnings to old endpoints, update documentation, and monitor usage. Remove old endpoints after clients have migrated (typically 6-12 months).
Does Modern PetstoreAPI support GraphQL and gRPC?
Yes. Unlike Swagger Petstore (REST only), Modern PetstoreAPI supports multiple protocols: 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 them the real costs: developer confusion, client bugs, security vulnerabilities, and technical debt. Use Apidog to demonstrate the violations in your current API. Compare your design to Modern PetstoreAPI and show the improvements.



