Website API Integration Basics: From REST to GraphQL
A content site is rarely "one program": pages need to load article lists, registration needs to submit forms, avatars need to be uploaded, search needs a third-party integration. Every one of those actions is an API call behind the scenes. An API turns that data exchange into a set of rules — the frontend requests according to the rules, and the backend answers accordingly. This article walks from REST to GraphQL to give you a solid foundation for wiring up your site's frontend and backend.
RESTful API Basics
REST (Representational State Transfer) is the most widely used API design style, and most public interfaces — GitHub, Stripe, Alipay's open platform — follow it. Its core idea is to treat every business object as a "resource", located by a URL and acted upon via an HTTP method.
Core principles
- Resource-oriented URLs (
/api/users,/api/articles) - HTTP method semantics: GET/read, POST/create, PUT/update, DELETE/delete
- Stateless: each request carries everything needed to complete it; the server keeps no session
- Uniform interface: consistent URL structure and response format, no special client conventions
Design example
Taking the article module as an example, a typical REST API is organized like this:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/articles |
List articles (with pagination params) |
| GET | /api/articles/:id |
Fetch a single article |
| POST | /api/articles |
Create an article |
| PUT | /api/articles/:id |
Update an article |
| DELETE | /api/articles/:id |
Delete an article |
Responses are usually JSON with a consistent envelope, such as { "code": 0, "data": [...], "message": "ok" }. Status codes matter too: 200 success, 201 created, 400 bad request, 401 unauthenticated, 404 not found, 429 rate limited, 500 server error. When the frontend gets a non-2xx status, it should branch into error handling rather than blindly parsing the body.
Frontend call example
// Use the Fetch API to call a REST endpoint
async function getArticles() {
const response = await fetch('/api/articles');
if (!response.ok) throw new Error('Failed to fetch');
return response.json();
}
// POST request
async function createArticle(data) {
const response = await fetch('/api/articles', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
return response.json();
}
Two things are easiest to miss when writing frontend calls. First, error handling: fetch only rejects on network failure — HTTP 4xx/5xx do not throw, so you must check response.ok yourself. Second, request cancellation: when users switch pages quickly, use AbortController to cancel stale requests so an old response does not overwrite the current page state. For a more systematic design guide, see REST API design guide.
GraphQL Basics
GraphQL is a query language created by Facebook. It flips the model from "backend defines endpoints" to "frontend asks for what it needs": the client declares which fields it wants, and the server returns only those. For sites reused across web and mobile, or pages whose field needs differ a lot, it reduces redundant payloads noticeably.
REST vs GraphQL
| Aspect | REST | GraphQL |
|---|---|---|
| Data fetching | Fixed structure | Client-defined |
| Over-fetching | Common | Does not happen |
| Multiple requests | Often needed | Single request |
| Learning curve | Low | Medium |
| Caching | Native HTTP cache | Needs extra setup |
| Tooling ecosystem | Mature | Growing fast |
GraphQL query example
# Query: fetch only the fields you need
query {
articles(first: 10) {
id
title
author {
name
}
}
}
# Mutation: create data
mutation {
createArticle(title: "Hello", content: "World") {
id
title
}
}
How to choose: a pragmatic take
For most small and mid-size sites, start with REST, add GraphQL later is the more stable path. The decision rules are simple:
- Many pages, wildly different field needs, mobile reuse → GraphQL's on-demand fetching pays off more;
- Small team, simple endpoints, lots of existing REST code → keep REST and avoid the maintenance cost of a schema and resolver layer;
- When "one page needs five calls to assemble its data" becomes a real pain, then consider GraphQL as an aggregation layer.
Whichever you pick, agree on how the API documentation is maintained: describe REST with OpenAPI/Swagger, and rely on GraphQL's built-in introspection. The documentation is the foundation of frontend/backend collaboration — when it drifts from the implementation, integration eats far too much time.
Version your API (/api/v2/... or an Accept header) so upgrades do not break old clients, and land cross-cutting concerns like auth, rate limiting, and logging via API security and auth. For backend engineering practice, see the backend integration category, such as Node.js API example; for storage choices, see database selection guide.
Frequently asked questions
- What if the endpoint is slow: check for N+1 queries first, then missing indexes, then consider CDN and database caching.
- Should I use an SDK: official SDKs bundle auth, retries, and types, but plain
fetchis perfectly fine for small projects. - How to debug CORS errors: the backend must return the correct
Access-Control-Allow-Origin; enablecredentialswhen cookies need to travel with the request. - How to separate environments: prepare
dev,staging, andprod, and switch baseURL via environment variables so test data never pollutes production endpoints.
Reference: Microsoft's Azure Architecture Center Web API design guidance is at https://learn.microsoft.com/azure/architecture/best-practices/api-design; the official GraphQL specification is at https://graphql.org/learn/.