Why Is the Swagger Petstore Example a Bad REST API Design?

The Swagger Petstore has taught millions of developers bad REST API practices for over a decade. Learn what's wrong with it and how Modern PetstoreAPI fixes these critical design flaws.

Ashley Innocent

Ashley Innocent

13 March 2026

Why Is the Swagger Petstore Example a Bad REST API Design?

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.”

💡
If you’re building or testing REST APIs, Apidog helps you validate API design against REST principles, test endpoint behavior, and catch design flaws before they reach production. You can import OpenAPI specs, run automated tests, and ensure your API follows proper REST conventions.
button

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:

  1. Junior developers learn anti-patterns - They don’t know these are mistakes
  2. Code generators perpetuate the issues - Generated SDKs inherit the flaws
  3. Documentation tools show bad examples - Swagger UI displays the Petstore by default
  4. 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:

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:

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:

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:

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:

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

Modern Standards

Multi-Protocol Support

Unlike Swagger Petstore (REST only), Modern PetstoreAPI supports:

See the protocols guide for implementation details.

Real Business Logic

Modern PetstoreAPI includes realistic features:

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:

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:

  1. Import Swagger Petstore: https://petstore.swagger.io/v2/swagger.json
  2. Import Modern PetstoreAPI: https://petstoreapi.com/openapi.json
  3. Run automated tests on both
  4. 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:

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:

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:

Step 4: Wrap Collections

Before:

[
  {"id": 1, "name": "Fluffy"},
  {"id": 2, "name": "Buddy"}
]

After:

{
  "data": [...],
  "pagination": {...},
  "links": {...}
}

Migration Strategy:

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:

Real-World Impact of Bad API Design

Bad API design has real costs:

Developer Confusion

When APIs violate REST principles, developers waste time:

Cost: Hours of developer time per integration

Client Bugs

Inconsistent APIs lead to client-side bugs:

Cost: Production incidents and customer impact

Security Vulnerabilities

Design flaws create security risks:

Cost: Data breaches and compliance violations

Technical Debt

Bad examples compound over time:

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:

  1. Explore Modern PetstoreAPI documentation
  2. Compare your API design to Modern PetstoreAPI patterns
  3. Import your OpenAPI spec into Apidog for validation
  4. Fix REST violations using the migration guide above
  5. 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.

Explore more

Socket.IO vs Native WebSocket: Which Should You Use?

Socket.IO vs Native WebSocket: Which Should You Use?

Socket.IO adds features like automatic reconnection and fallbacks, but Native WebSocket is simpler and faster. Learn when to use each and how Modern PetstoreAPI implements both.

13 March 2026

When Should You Use MQTT Instead of HTTP for APIs?

When Should You Use MQTT Instead of HTTP for APIs?

MQTT excels for IoT devices with limited bandwidth and unreliable networks. Learn when MQTT beats HTTP and how Modern PetstoreAPI uses MQTT for pet tracking devices and smart feeders.

13 March 2026

WebSocket vs Server-Sent Events: Which Is Better for Real-Time APIs?

WebSocket vs Server-Sent Events: Which Is Better for Real-Time APIs?

WebSocket and Server-Sent Events both enable real-time communication, but they solve different problems. Learn when to use each and how Modern PetstoreAPI implements both protocols.

13 March 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs