When one application asks another for a customer record, a delivery price or a weather forecast, the exchange often happens through an API. The idea is simple: the client sends a request in an agreed format, and the server returns a response.
The request carries four useful pieces
A web API request usually contains an address, an HTTP method, headers and sometimes a body.
The location of the resource, such as /orders/42.
The action: GET reads, POST creates, PUT or PATCH changes, and DELETE removes.
Extra context such as the content type, authentication token or preferred response format.
The data being sent, often encoded as JSON.
Imagine that Application A needs to create a support ticket in Application B. It sends a POST request to the ticket endpoint with a JSON body containing the subject and message. Application B validates the data, stores the ticket and sends back a response.
A small Flask example
This server accepts JSON at /tickets, checks that a subject exists and returns a new ticket identifier.
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.post("/tickets")
def create_ticket():
data = request.get_json(silent=True) or {}
if not data.get("subject"):
return jsonify(error="subject is required"), 400
ticket = {"id": 101, "subject": data["subject"], "status": "open"}
return jsonify(ticket), 201The client can send:
{
"subject": "Printer is offline"
}A successful response uses status 201 and returns the created ticket. A bad request uses status 400 and explains what is missing. That status and message are part of the API contract.
The response tells the client what happened
Applications should not assume that every response is successful or even valid JSON. Networks fail, services time out and credentials expire.
Build the client for failure as well as success
Do not let one slow service block the application forever.
Handle expected outcomes such as 201, 400, 401 and 404.
Confirm required fields before using them.
Retry temporary failures with a delay, but avoid repeating actions that could create duplicates.
It makes a problem much easier to trace across two systems.
Never place passwords or private API keys in source code. Load secrets from a protected environment or secret manager, send them only over HTTPS and give each credential the least access it needs.
Test the contract from both sides
Before connecting a real client, use Flask's test client or an API testing tool to try normal, missing and invalid data. Agree on field names, status codes and error shapes. If the server changes that contract, version the API or give clients time to migrate.
- Document one working request and its response.
- Document common error responses.
- Use HTTPS and protected credentials.
- Validate input on the server and output on the client.
- Add timeouts, useful logs and safe retry behaviour.
