DEV Community

1xApi
1xApi

Posted on • Originally published at 1xapi.com

Top 10 Free Public APIs Every Developer Should Know in 2026

Every API interaction is a conversation. Your client sends a request, and the server responds — not just with data, but with a status code that tells the client exactly what happened. Understanding these codes is fundamental to building robust APIs and resilient clients.

Without proper status codes, debugging becomes guesswork. Did the request fail because of bad input? Authentication issues? A server crash? The right status code answers these questions instantly, saving developers hours of troubleshooting and enabling clients to handle errors gracefully.

2xx Success Codes

Success codes confirm that the server received, understood, and processed the request.

200 OK

The standard success response. Use it when returning data — a fetched resource, search results, or the outcome of an operation.

GET /api/users/42 → 200 OK
{ "id": 42, "name": "Alice", "email": "alice@example.com" }
Enter fullscreen mode Exit fullscreen mode

201 Created

Use this when a new resource has been created. Always pair it with a Location header pointing to the new resource.

POST /api/users → 201 Created
Location: /api/users/43
{ "id": 43, "name": "Bob" }
Enter fullscreen mode Exit fullscreen mode

204 No Content

The request succeeded, but there's nothing to send back. Perfect for DELETE operations or updates where the client doesn't need the modified resource returned.

DELETE /api/users/42 → 204 No Content
(empty body)
Enter fullscreen mode Exit fullscreen mode

When to choose which: If you're returning data, use 200. If you created something, use 201. If the action succeeded but there's no meaningful body, use 204.

3xx Redirection Codes

Redirection codes are less common in APIs than in web browsers, but they still have important uses.

301 Moved Permanently

The resource has a new permanent URL. Clients and intermediaries should update their bookmarks. Use this when you've restructured your API and want to guide clients to the new endpoint.

302 Found (Temporary Redirect)

The resource is temporarily at a different URL. The client should continue using the original URL for future requests. Useful for temporary maintenance redirects or OAuth flows.

304 Not Modified

A powerful caching tool. When a client sends a conditional request with If-None-Match or If-Modified-Since headers, and the resource hasn't changed, respond with 304. The client uses its cached copy, saving bandwidth and processing time.

GET /api/products/99
If-None-Match: "etag-abc123"
→ 304 Not Modified
Enter fullscreen mode Exit fullscreen mode

4xx Client Error Codes

These indicate the client did something wrong. The request should be modified before retrying.

400 Bad Request

The server can't process the request due to malformed syntax — invalid JSON, missing required fields, or wrong data types.

401 Unauthorized

Authentication is missing or invalid. The client needs to provide valid credentials. Despite the name, this is about authentication, not authorization.

403 Forbidden

The client is authenticated but doesn't have permission to access this resource. Unlike 401, re-authenticating won't help — the user simply lacks the required privileges.

404 Not Found

The requested resource doesn't exist. This is also commonly used to hide the existence of resources from unauthorized users (instead of returning 403).

409 Conflict

The request conflicts with the current state of the resource. Common scenarios include duplicate entries, version conflicts in optimistic locking, or trying to delete a resource that has dependencies.

422 Unprocessable Entity

The syntax is valid, but the content is semantically wrong. Think of it as "I understand your JSON, but the data doesn't make sense" — like a negative age or an end date before a start date.

429 Too Many Requests

The client has hit a rate limit. Always include a Retry-After header so the client knows when to try again.

429 Too Many Requests
Retry-After: 60
{ "error": "rate_limit_exceeded", "message": "Try again in 60 seconds" }
Enter fullscreen mode Exit fullscreen mode

5xx Server Error Codes

These indicate something went wrong on the server side. The client's request may have been valid.

500 Internal Server Error

The catch-all for unexpected server failures — unhandled exceptions, null pointer errors, or configuration issues. If you're seeing lots of 500s, something needs fixing on the backend.

502 Bad Gateway

The server, acting as a gateway or proxy, received an invalid response from an upstream server. Common in microservice architectures when a downstream service is misbehaving.

503 Service Unavailable

The server is temporarily unable to handle requests — typically due to maintenance or overload. Like 429, include a Retry-After header when possible.

Designing Proper Error Responses

A status code alone isn't enough. Your error responses should be structured and consistent:

{
  "error": {
    "code": "validation_error",
    "message": "The request body contains invalid fields.",
    "details": [
      {
        "field": "email",
        "issue": "Invalid email format"
      },
      {
        "field": "age",
        "issue": "Must be a positive integer"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Key principles:

  • Machine-readable error code — clients can switch on error.code without parsing messages
  • Human-readable message — helpful for debugging
  • Details array — specific field-level errors for validation failures
  • Consistent structure — every error follows the same format

Server-Side: Express.js Error Handling Middleware

Here's a practical error handling middleware that maps custom errors to proper HTTP responses:

class AppError extends Error {
  constructor(statusCode, code, message, details = null) {
    super(message);
    this.statusCode = statusCode;
    this.code = code;
    this.details = details;
  }
}

// Error handling middleware (must have 4 parameters)
function errorHandler(err, req, res, next) {
  if (err instanceof AppError) {
    return res.status(err.statusCode).json({
      error: {
        code: err.code,
        message: err.message,
        ...(err.details && { details: err.details }),
      },
    });
  }

  // Unexpected errors → 500
  console.error('Unhandled error:', err);
  res.status(500).json({
    error: {
      code: 'internal_error',
      message: 'An unexpected error occurred.',
    },
  });
}

// Usage in routes
app.post('/api/users', (req, res) => {
  if (!req.body.email) {
    throw new AppError(422, 'validation_error', 'Missing required fields', [
      { field: 'email', issue: 'Email is required' },
    ]);
  }
  // ... create user
});

app.use(errorHandler);
Enter fullscreen mode Exit fullscreen mode

Client-Side: Handling Status Codes with Fetch

On the client side, handle different status codes explicitly rather than treating all errors the same:

async function apiRequest(url, options = {}) {
  const response = await fetch(url, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
  });

  if (response.ok) {
    // 204 has no body
    if (response.status === 204) return null;
    return response.json();
  }

  const error = await response.json().catch(() => ({}));

  switch (response.status) {
    case 401:
      // Redirect to login or refresh token
      window.location.href = '/login';
      break;
    case 403:
      throw new Error('You do not have permission for this action.');
    case 404:
      throw new Error('The requested resource was not found.');
    case 422:
      // Return structured validation errors for form display
      throw { type: 'validation', details: error.error?.details || [] };
    case 429:
      // Retry after the specified delay
      const retryAfter = response.headers.get('Retry-After') || 60;
      await new Promise((r) => setTimeout(r, retryAfter * 1000));
      return apiRequest(url, options);
    default:
      throw new Error(error.error?.message || 'Something went wrong.');
  }
}
Enter fullscreen mode Exit fullscreen mode

Wrapping Up

HTTP status codes are the universal language of API communication. Use them correctly, and your API becomes self-documenting — clients know exactly what happened and what to do next. Pair meaningful status codes with structured error responses, and you'll build APIs that developers genuinely enjoy working with.

The golden rule: be specific. A 422 with field-level details is infinitely more useful than a generic 400 with "Bad Request." Your future self — and every developer consuming your API — will thank you.


Published by 1xAPI

Top comments (0)