Rest Apis

By the end of this lesson you'll be able to build a working REST API in plain PHP — reading the HTTP method, parsing a JSON request body, returning JSON with the right status code, routing, adding CORS — and then call an API back from PHP.

Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.

Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ Returning JSON

A web page sends back HTML; an API (Application Programming Interface) sends back data — almost always as JSON (a plain-text format that looks like a PHP array: {' "key":"value" '} ). Two steps turn any PHP into a JSON response. First, send a header — a behind-the-scenes label on the response — telling the client the body is JSON. Then build a normal array and pass it through json_encode() , which serialises it into a JSON string.

That's the whole idea of an API response: a PHP array in, a JSON string out, with a Content-Type: application/json header so the caller's code knows to parse it as data rather than display it as text.

2️⃣ HTTP Methods: GET, POST, PUT, DELETE

Every request arrives with an HTTP method (also called a verb ) that states the caller's intent. GET reads data, POST creates something new, PUT updates an existing thing, and DELETE removes it. PHP hands you the method in the superglobal $_SERVER['REQUEST_METHOD'] — a built-in array describing the request. You branch on it to decide what to do.

Notice the else branch: if a caller uses a method this endpoint doesn't support, you reply 405 Method Not Allowed rather than silently doing the wrong thing. Reporting how it went is the API's job, which is the next section.

3️⃣ Reading the JSON Body & Status Codes

A POST or PUT carries its data in the request body as raw JSON. You can't read that from $_POST (that's only for HTML forms) — instead you read the raw stream php://input with file_get_contents() , then json_decode() it into a PHP array. Always validate the result: json_decode returns null for missing or malformed JSON. A status code is the numeric verdict on the response — set it with http_response_code() before you echo anything.

The flow is read → validate → respond. Invalid input gets 400 Bad Request and an exit so nothing else runs; valid input that creates a record gets 201 Created . The ?? is the null coalescing operator — "use this default if the key is missing".

4️⃣ A Simple Router & CORS

A real endpoint handles a whole resource — for /books that means "list all", "get one by id", "create", and so on. A tiny router reads the method and the id (here from the query string, ?id=1 ) and dispatches to the right branch. If a browser app on another domain will call your API, you also need CORS headers (Cross-Origin Resource Sharing) — without them the browser blocks the response. Browsers send a preflight OPTIONS request first, which you answer with 204 No Content .

This single file is now a working API: list, fetch-by-id with a real 404 , create with 201 , and a 405 for anything else — all callable from any browser thanks to the CORS headers.

5️⃣ Consuming an API from PHP

APIs talk to each other, so your PHP often needs to call someone else's API. Two built-in tools do the job. cURL is the powerful one: curl_init() opens a request, curl_setopt() configures it (the key option is CURLOPT_RETURNTRANSFER so the body is returned as a string), and curl_exec() fires it. For a simple GET, file_get_contents() fetches a URL in one line. Either way, you json_decode() the response back into a PHP array.

Now you try. The endpoint below is almost complete — fill in each ___ using the 👉 hint, then check it against the Output panel.

One more. This endpoint should accept only DELETE . Fill in the method key, the verb, and the "not allowed" status code.

📋 Quick Reference — Building a PHP API

No code is filled in this time — just a brief and an outline. Build the endpoint yourself, serve it with php -S localhost:8000 , then test each case with curl and check it against the expected output in the comments. This is the read-method → read-body → validate → respond loop you'll use on every real endpoint.

Practice quiz

Which two steps turn PHP output into a JSON API response?

  • echo the array, then call header()
  • Call json_decode(), then print
  • Send header('Content-Type: application/json'), then echo json_encode($array)
  • Set http_response_code(200) and echo HTML

Answer: Send header('Content-Type: application/json'), then echo json_encode($array). Send the JSON content-type header, then build a PHP array and pass it through json_encode() to serialise it into a JSON string.

Which superglobal tells you the HTTP method of the request?

  • REQUEST_METHOD

Answer: REQUEST_METHOD. $_SERVER['REQUEST_METHOD'] holds GET/POST/PUT/DELETE; you branch on it to decide what the endpoint does.

Which REST verb is used to create a new resource?

  • GET
  • PUT
  • DELETE
  • POST

Answer: POST. GET reads, POST creates, PUT updates an existing thing, and DELETE removes it.

Why read php://input instead of $_POST for a JSON API?

  • $_POST is deprecated
  • $_POST is only populated for form submissions, not a raw JSON body
  • php://input is faster
  • $_POST cannot hold strings

Answer: $_POST is only populated for form submissions, not a raw JSON body. $_POST is filled only for form-encoded bodies; REST clients send raw JSON, so you read php://input and json_decode it.

After json_decode() of the request body, what must you always do?

  • Validate it — json_decode returns null for missing or invalid JSON
  • Immediately save it to the database
  • Re-encode it
  • Send it back unchanged

Answer: Validate it — json_decode returns null for missing or invalid JSON. json_decode returns null on missing/malformed JSON, so check the result (e.g. is_array and required fields) before using it.

Which status code should a successful POST that creates a record return?

  • 200 OK
  • 204 No Content
  • 201 Created
  • 404 Not Found

Answer: 201 Created. A successful creation returns 201 Created; set it with http_response_code(201) before echoing the new record.

Which status code means the request body was invalid?

  • 405 Method Not Allowed
  • 400 Bad Request
  • 201 Created
  • 500 Server Error

Answer: 400 Bad Request. Invalid input gets 400 Bad Request (often followed by exit), so nothing else runs on a bad body.

When must http_response_code() and header() be called?

  • After echoing the JSON body
  • Only inside json_encode()
  • At the very end of the script
  • Before any output — once a byte is sent, headers can't be changed

Answer: Before any output — once a byte is sent, headers can't be changed. Headers and status codes must be set before the first byte of output, or you get 'headers already sent'.

What is CORS and which header enables a cross-origin browser call?

  • A caching rule; Cache-Control
  • A browser security rule; Access-Control-Allow-Origin
  • An auth scheme; Authorization
  • A compression setting; Content-Encoding

Answer: A browser security rule; Access-Control-Allow-Origin. CORS is a browser rule that blocks cross-domain reads by default; Access-Control-Allow-Origin permits it (cURL ignores CORS).

Which cURL option makes curl_exec() return the response body as a string?

  • CURLOPT_POST
  • CURLOPT_HEADER
  • CURLOPT_RETURNTRANSFER
  • CURLOPT_URL

Answer: CURLOPT_RETURNTRANSFER. Set CURLOPT_RETURNTRANSFER to true so curl_exec() returns the body as a string instead of printing it; then json_decode it.