Software Engineering·July 21, 2026·8 min read

Understanding APIs

An API lets two pieces of software talk to each other. This guide explains REST APIs, webhooks, authentication, and status codes in plain English — with real examples.

apirestwebhooksintegrationfundamentals

An API (Application Programming Interface) is how two pieces of software communicate. When your app processes a payment with Stripe, sends email through SendGrid, or gets an AI response from OpenAI — that's an API call.

If Cartara flagged this concept in your diff, you likely added or modified code that calls an external service, defines API routes, or handles responses.


What Is an API?

Think of an API like a waiter at a restaurant. You don't walk into the kitchen and cook your own food — you tell the waiter what you want, the waiter communicates it, and the result comes back to you. The API is the waiter: it takes your request, passes it to another system, and returns the result.

APIs let you build on top of existing services instead of building everything yourself:

  • Payments → Stripe's API
  • Email → SendGrid or Resend's API
  • Authentication → Clerk or Supabase's API
  • AI → OpenAI or Anthropic's API

How REST APIs Work

REST (Representational State Transfer) is the most common API style. Nearly every web service uses it.

Resources and Endpoints

A REST API is organised around resources — the things your app works with (users, orders, products). Each resource has a URL called an endpoint, and you interact with it using HTTP methods:

MethodWhat It DoesExample
GETRetrieve dataFetch a user's profile
POSTCreate somethingSubmit a new order
PUT / PATCHUpdate somethingEdit a user's email
DELETERemove somethingDelete a record

A typical set of endpoints for a users resource:

```
GET /users → list all users
GET /users/42 → get user with ID 42
POST /users → create a new user
PUT /users/42 → update user 42
DELETE /users/42 → delete user 42
```

A Real API Call

When your app asks OpenAI to generate text, it sends a POST request:

```
POST https://api.openai.com/v1/chat/completions
Authorization: Bearer sk-your-api-key
Content-Type: application/json

{
"model": "gpt-4o",
"messages": [{ "role": "user", "content": "Summarise this article..." }]
}
```

OpenAI processes it and responds:

```json
{
"choices": [{
"message": { "content": "Here is the summary..." }
}]
}
```

This request-response pattern — send a request, get a response — is how every REST API works.

Status Codes

Every API response includes a status code telling you what happened:

CodeMeaning
200Success
201Created successfully
400Bad request — something wrong with what you sent
401Unauthorised — API key missing or invalid
403Forbidden — you don't have permission
404Not found — the resource doesn't exist
429Too many requests — you've hit the rate limit
500Server error — something went wrong on their end

When debugging an API error, the status code is the first thing to check.

Authentication

Most APIs require authentication to prove who you are. The most common methods:

API Keys — a unique string you include in every request. Simple, but store them in environment variables, never in your code. See Secrets and Config Management.

Bearer Tokens (JWTs) — a short-lived token your app gets after login, included in subsequent requests. More secure for user-facing actions.

OAuth — lets users grant your app access to their accounts on other services ("Sign in with Google"). The standard for user-authorised integrations.


What You'll See in Your Code

API-related code typically shows up in Cartara diffs as:

Fetch/axios calls — requests to external services:
```ts
const response = await fetch('https://api.stripe.com/v1/customers', {
method: 'POST',
headers: {
'Authorization': Bearer ${process.env.STRIPE_SECRET_KEY},
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: user.email }),
});
```

Route handlers — your app's own API endpoints:
```ts
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
if (!user) return res.status(404).json({ error: 'User not found' });
res.json(user);
});
```

Environment variables — API keys loaded from config:
```ts
const apiKey = process.env.OPENAI_API_KEY;
```


Webhooks

Why Webhooks Exist

REST APIs work on a pull model: you ask, they answer. But what if you need to know when something happens on their end?

You could keep asking "Has the payment gone through?" every second — this is called polling and it's wasteful. A webhook flips the model: you give the service a URL, and it notifies you when something happens.

REST is a phone call — you dial, you ask, you get an answer.
A webhook is a push notification — they ping you when something occurs.

How Webhooks Work

  1. You register a URL in the service's dashboard (e.g. https://yourapp.com/webhooks/stripe)
  2. An event occurs on their platform (payment completes, user signs up)
  3. They send a POST request to your URL with event data
  4. Your app processes it and responds with 200 to confirm receipt

Example Stripe webhook payload:
```json
{
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_abc123",
"amount": 4999,
"currency": "usd"
}
}
}
```

Webhook Security

Anyone can send a POST request to your webhook URL — always verify the request came from the real service. Most providers sign payloads with a secret key (HMAC signature). Always verify this signature before processing the event.

When to Use Each

ScenarioUse
Fetch a user's profileREST (GET)
Create a new recordREST (POST)
React to a completed paymentWebhook
React to a new GitHub commitWebhook

Rule of thumb: REST when you're initiating an action. Webhooks when you need to react to something that happened elsewhere.


Other API Types

GraphQL — the client specifies exactly what data it needs in a single query. Popular with complex frontends; used by GitHub and Shopify.

WebSockets — a persistent two-way connection for real-time features: live chat, collaborative editing, live dashboards. See WebSockets and Real-Time Communication.

gRPC — high-performance protocol mostly used for internal service-to-service communication.


Related concepts

API Design
How to design APIs that are predictable, consistent, and easy to build on — naming, versioning, errors, pagination, and more.
Database Fundamentals
A database stores and organises your app's data. This guide explains SQL vs NoSQL, when to use each, core concepts like indexes and transactions, and how to get started.
System Design Basics
System design is how the individual parts of your app — database, cache, queue, and APIs — fit together into something that's fast, reliable, and able to grow. This guide covers the core building blocks and the decisions that shape every system.

Turn shipping into understanding

Cartara measures what your team actually learns from every AI coding session.

Join the waitlist