POST with JSON

Sending data to a server with correct headers and body encoding

When sending data to a server, you need to specify the HTTP method as POST (or PUT/PATCH), set the Content-Type header to indicate the format, and serialize the data in the request body.

For JSON APIs, you must set Content-Type: application/json and use JSON.stringify() to convert your JavaScript object to a JSON string.

Basic POST Request

async function createUser(userData) { const response = await fetch('https://api.example.com/users', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(userData) }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } return response.json(); } // Usage const newUser = await createUser({ name: 'Alice Smith', email: 'alice@example.com' });

Three essential elements:

  • method: 'POST' — tells the server you're sending data
  • Content-Type: application/json — tells the server the format of your data
  • body: JSON.stringify(data) — the actual data, serialized as a JSON string

With Validation Error Handling

async function createUser(userData) { const response = await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(userData) }); const data = await response.json(); // Handle validation errors (usually 400/422) if (!response.ok) { if (response.status === 422) { // Server returned validation errors throw { type: 'validation', errors: data.errors }; } throw new Error(data.message || 'Request failed'); } return data; } // Usage with error handling try { const user = await createUser({ email: 'invalid' }); } catch (error) { if (error.type === 'validation') { // Display field-level errors to user error.errors.forEach(e => console.log(e.field, e.message)); } else { console.error('Unexpected error:', error); } }

APIs often return structured error responses for validation failures. Parse the response body even on error to extract field-specific error messages for better UX.

Reusable API Client

class ApiClient { constructor(baseUrl) { this.baseUrl = baseUrl; } async request(endpoint, options = {}) { const url = `${this.baseUrl}${endpoint}`; const config = { headers: { 'Content-Type': 'application/json', ...options.headers }, ...options }; if (config.body && typeof config.body === 'object') { config.body = JSON.stringify(config.body); } const response = await fetch(url, config); if (!response.ok) { const error = await response.json().catch(() => ({})); throw new Error(error.message || `HTTP ${response.status}`); } return response.json(); } get(endpoint) { return this.request(endpoint); } post(endpoint, body) { return this.request(endpoint, { method: 'POST', body }); } put(endpoint, body) { return this.request(endpoint, { method: 'PUT', body }); } delete(endpoint) { return this.request(endpoint, { method: 'DELETE' }); } } // Usage const api = new ApiClient('https://api.example.com'); const user = await api.post('/users', { name: 'Alice' });

A wrapper class encapsulates common patterns: setting headers, serializing JSON, handling errors. This reduces boilerplate and ensures consistent behavior.

Try It Live

Request

Fill the form and click "Create User"

Response

Response will appear here

Common Mistakes

  • Forgetting Content-Type: application/json — the server may not parse your data
  • Sending an object instead of JSON.stringify(object) — results in "[object Object]"
  • Not checking response.ok — 400/500 errors won't throw automatically