How to Build a Simple REST API in PHP for Beginners – Connect Your Project to Android or React (2026)

PHP Tutorial REST API Beginners 2026 Updated Full Working Code Connect to Android / React
AI + Beginner Dev Guide — Updated April 2026

How to Build a Simple REST API in PHP for Beginners — Connect Your Project to Android or React (2026)

Your PHP management system runs beautifully on a browser. But what if a mobile app needed the same data? Or a React frontend? The answer is a REST API — and you can build a working one in PHP and MySQL in under an hour, without any framework, using only skills you already have. This is the complete beginner’s guide.

⚡ No framework required 📱 Connect to Android or React 🧩 Full working code included 🧪 API tester included

Every popular app you use — Instagram, Uber, your university’s student portal — is powered by an API. When the Instagram app on your phone shows you photos, it is not loading a PHP page. It is sending a request to an API that returns a list of photos as JSON data, which the app then displays however it wants.

This separation between “the thing that stores data” (your PHP + MySQL project) and “the thing that shows data” (a browser, a mobile app, a React component) is what REST APIs make possible. And the great news for PHP developers is that you already know everything you need to build one. A REST API in PHP is just PHP — no new language, no complex framework, just the same PHP and MySQL you already use, organised differently.

By the end of this guide you will have a working REST API built on top of a PHP management system that returns JSON, handles different types of requests, and can be connected to an Android app, a React frontend, or tested using Postman or a browser.

💡 What this guide builds: A REST API for a customer management system (based on the ISP or Hospital projects from Codezips) with 5 endpoints: get all customers, get one customer, add a customer, update a customer, and delete a customer. The same pattern applies to any table in any of your existing PHP projects.

What Is a REST API? — The Restaurant Explanation

Before writing a single line of code, you need to understand what a REST API actually is. The best explanation is a restaurant analogy that has been used in developer education for over a decade — because it is genuinely the clearest way to understand the concept.

🍽 The Restaurant Analogy — How REST APIs Work

📱
Client (You)
Android app, React website, Postman, or browser
→ Request →

← Response ←
🍳
Server (Your PHP API)
PHP processes the request, talks to MySQL, returns JSON

In a restaurant, you (the customer) do not walk into the kitchen and cook. You look at the menu, tell the waiter what you want, and the kitchen prepares it and brings it out. The REST API is the waiter — it takes your request to the kitchen (database), gets what you asked for, and brings it back to you in a format you can understand (JSON).

Click each HTTP method below to see what it does and when to use it:

GET
READ
Get all customers
Get customer #5
GET retrieves data without changing anything on the server. It is safe to call multiple times — the result is the same each time. Use GET whenever you want to read records from your database. Examples: get all customers, get a specific bill, get a list of internet plans. GET requests can be made from a browser URL bar directly.
POST
CREATE
Add new customer
Submit new bill
POST creates a new resource on the server. It sends data in the request body (as JSON). Each POST call creates a new record — so calling it twice creates two records. Use POST for: adding a new customer, creating a new bill, registering a new user. Cannot be tested from a browser URL bar — use Postman or fetch() in JavaScript.
PUT
UPDATE
Update customer name
Change plan price
PUT replaces an existing resource with new data. You send the complete updated version of the record in the request body. Use PUT when you want to update an existing record — like changing a customer’s plan or updating their address. The URL includes the ID of the record to update: PUT /api/customers/5
DELETE
REMOVE
Delete customer #5
Remove expired bill
DELETE removes a resource from the server. The URL includes the ID of the record to delete: DELETE /api/customers/5. Calling DELETE on the same ID twice: the first time deletes it, the second time returns a 404 (not found). Be careful — deletions are permanent unless you implement soft deletes (marking as deleted rather than removing).

HTTP Methods Quiz — Test Your Understanding

Quick quiz to make sure you understand HTTP methods before writing any code. 5 questions — each one based on a real scenario from PHP projects:

⚡ HTTP Methods for PHP Developers — 5 Questions

Loading…


Understanding JSON — The Language APIs Speak

REST APIs communicate in JSON (JavaScript Object Notation). JSON is just a way of representing data as text that any programming language can read. Your PHP project already uses arrays to store data — JSON is essentially the same thing, written in a universal format.

Here is the same customer data expressed as a PHP array, a MySQL row, and JSON — so you can see how they relate:

PHP PHP array → JSON → MySQL row — same data, three formats

// PHP Array (how your PHP code stores it)
$customer = [
    'id'        => 5,
    'name'      => 'John Smith',
    'email'     => 'john@example.com',
    'plan_id'   => 2,
    'status'    => 'active'
];

// JSON (how the API sends it to Android/React/any client)
// json_encode() converts a PHP array to JSON automatically
{
    "id": 5,
    "name": "John Smith",
    "email": "john@example.com",
    "plan_id": 2,
    "status": "active"
}

// MySQL Row (how it's stored in the database)
// SELECT id, name, email, plan_id, status FROM customers WHERE id = 5;
// Returns: 5 | John Smith | john@example.com | 2 | active

// The magic: mysqli_fetch_assoc() returns a PHP array from MySQL,
// then json_encode() turns that array into JSON.
// That's all your API needs to do for a GET request.

Project Structure — What You Will Build

The 5 API endpoints

GET /api/customers.php
Returns all customers as a JSON array. The Android or React app calls this to display a customer list.
Example response
[{"id":1,"name":"John Smith","email":"john@example.com","status":"active"},{"id":2,"name":"Sarah Lee","email":"sarah@example.com","status":"active"}]
GET /api/customers.php?id=5
Returns a single customer by ID. Used when the app needs details for one specific customer.
Example response
{"id":5,"name":"John Smith","email":"john@example.com","plan_id":2,"status":"active","plan_name":"100Mbps Standard"}
POST /api/customers.php
Creates a new customer. The app sends JSON in the request body with the customer’s details.
Example response
{"success":true,"message":"Customer created successfully","id":42}
PUT /api/customers.php?id=5
Updates an existing customer’s details. The app sends the updated fields as JSON in the request body.
Example response
{"success":true,"message":"Customer updated successfully"}
DELETE /api/customers.php?id=5
Deletes a customer by ID. Returns a success or error message as JSON.
Example response
{"success":true,"message":"Customer deleted successfully"}

File structure

Folder Structure Add these files to your existing PHP project

your-project-folder/
├── index.php              (your existing main file — unchanged)
├── config/
│   └── dbconnection.php   (your existing database connection — unchanged)
├── api/                   ← NEW folder
│   ├── config.php         ← NEW: CORS headers and shared functions
│   └── customers.php      ← NEW: the main API file for customer endpoints
💡 You are not replacing your existing PHP system — you are adding to it. Your browser-based admin dashboard continues to work exactly as before. The api/ folder is a completely separate set of files that any client (mobile app, React, Postman) can call independently. Same database, two ways to access it.

1Create api/ folder
2config.php (CORS)
3GET all customers
4GET one customer
5POST create
6PUT update
7DELETE
8Test with Postman

Step 1 — Create the api/ Folder and config.php

Inside your XAMPP htdocs project folder, create a new folder called api. Inside it, create a file called config.php. This file does two important things: (1) it sets CORS headers so your API can be called from mobile apps and other websites, and (2) it includes your database connection.

PHP api/config.php — CORS headers + database connection

<?php
// ─────────────────────────────────────────────────────
// CORS Headers — allow any client to call this API
// For production: change * to your specific domain
// ─────────────────────────────────────────────────────
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

// Handle browser preflight OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}

// ─────────────────────────────────────────────────────
// Database Connection
// Update these values to match your XAMPP setup
// ─────────────────────────────────────────────────────
$host   = 'localhost';
$dbname = 'isp_db';    // Your database name from phpMyAdmin
$user   = 'root';
$pass   = '';           // Blank by default on XAMPP

$conn = mysqli_connect($host, $user, $pass, $dbname);

if (mysqli_connect_errno()) {
    http_response_code(500);
    echo json_encode([
        'success' => false,
        'message' => 'Database connection failed: ' . mysqli_connect_error()
    ]);
    exit();
}
?>
⚠️ What is CORS? CORS (Cross-Origin Resource Sharing) is a browser security rule that by default prevents a website on one domain from calling an API on another domain. Setting Access-Control-Allow-Origin: * tells the browser “this API accepts requests from any origin.” For a student project or portfolio API, this is fine. For a production application with real user data, restrict this to specific domains.

Step 2 — Build the Complete API File

Create api/customers.php. This single file handles all 5 endpoints by checking what HTTP method was used and whether an id parameter was provided. This is the most common pattern for a simple PHP REST API without a framework.

PHP api/customers.php — Complete REST API (all 5 endpoints)

<?php
// Include CORS headers and database connection
require_once 'config.php';

// Get the HTTP method and optional customer ID from the URL
// Example: GET /api/customers.php?id=5
$method = $_SERVER['REQUEST_METHOD'];
$id     = isset($_GET['id']) ? (int)$_GET['id'] : null;

// Route requests to the correct handler based on method and ID
switch ($method) {
    case 'GET':
        $id ? getCustomer($conn, $id) : getAllCustomers($conn);
        break;
    case 'POST':
        createCustomer($conn);
        break;
    case 'PUT':
        $id ? updateCustomer($conn, $id) : errorResponse(400, 'Customer ID required for update');
        break;
    case 'DELETE':
        $id ? deleteCustomer($conn, $id) : errorResponse(400, 'Customer ID required for delete');
        break;
    default:
        errorResponse(405, 'Method not allowed');
}

// ─────────────────────────────────────────────
// GET all customers
// Endpoint: GET /api/customers.php
// ─────────────────────────────────────────────
function getAllCustomers($conn) {
    $query  = "SELECT c.id, c.name, c.email, c.phone, c.status,
                      p.plan_name, p.price
               FROM customers c
               LEFT JOIN internet_plans p ON c.plan_id = p.id
               WHERE c.status = 'active'
               ORDER BY c.name ASC";
    $result = mysqli_query($conn, $query);
    $customers = [];
    while ($row = mysqli_fetch_assoc($result)) {
        $customers[] = $row;
    }
    http_response_code(200);
    echo json_encode($customers);
}

// ─────────────────────────────────────────────
// GET one customer by ID
// Endpoint: GET /api/customers.php?id=5
// ─────────────────────────────────────────────
function getCustomer($conn, $id) {
    $stmt = mysqli_prepare($conn,
        "SELECT c.*, p.plan_name, p.price
         FROM customers c
         LEFT JOIN internet_plans p ON c.plan_id = p.id
         WHERE c.id = ?");
    mysqli_stmt_bind_param($stmt, 'i', $id);
    mysqli_stmt_execute($stmt);
    $result   = mysqli_stmt_get_result($stmt);
    $customer = mysqli_fetch_assoc($result);
    if ($customer) {
        http_response_code(200);
        echo json_encode($customer);
    } else {
        errorResponse(404, 'Customer not found');
    }
}

// ─────────────────────────────────────────────
// POST — create a new customer
// Endpoint: POST /api/customers.php
// Body (JSON): {"name":"...","email":"...","phone":"...","plan_id":2}
// ─────────────────────────────────────────────
function createCustomer($conn) {
    $body = json_decode(file_get_contents('php://input'), true);
    if (!$body || !isset($body['name']) || !isset($body['email'])) {
        errorResponse(400, 'Name and email are required');
        return;
    }
    $name    = mysqli_real_escape_string($conn, $body['name']);
    $email   = mysqli_real_escape_string($conn, $body['email']);
    $phone   = mysqli_real_escape_string($conn, $body['phone'] ?? '');
    $plan_id = (int)($body['plan_id'] ?? 1);

    $stmt = mysqli_prepare($conn,
        "INSERT INTO customers (name, email, phone, plan_id, status)
         VALUES (?, ?, ?, ?, 'active')");
    mysqli_stmt_bind_param($stmt, 'sssi', $name, $email, $phone, $plan_id);
    if (mysqli_stmt_execute($stmt)) {
        http_response_code(201);
        echo json_encode([
            'success' => true,
            'message' => 'Customer created successfully',
            'id'      => mysqli_insert_id($conn)
        ]);
    } else {
        errorResponse(500, 'Failed to create customer: ' . mysqli_error($conn));
    }
}

// ─────────────────────────────────────────────
// PUT — update an existing customer
// Endpoint: PUT /api/customers.php?id=5
// Body (JSON): {"name":"New Name","email":"new@email.com"}
// ─────────────────────────────────────────────
function updateCustomer($conn, $id) {
    $body = json_decode(file_get_contents('php://input'), true);
    if (!$body) { errorResponse(400, 'No data provided'); return; }

    $name    = mysqli_real_escape_string($conn, $body['name']    ?? '');
    $email   = mysqli_real_escape_string($conn, $body['email']   ?? '');
    $phone   = mysqli_real_escape_string($conn, $body['phone']   ?? '');
    $plan_id = (int)($body['plan_id'] ?? 1);

    $stmt = mysqli_prepare($conn,
        "UPDATE customers SET name=?, email=?, phone=?, plan_id=?
         WHERE id=?");
    mysqli_stmt_bind_param($stmt, 'sssii', $name, $email, $phone, $plan_id, $id);
    if (mysqli_stmt_execute($stmt) && mysqli_stmt_affected_rows($stmt) > 0) {
        http_response_code(200);
        echo json_encode(['success' => true, 'message' => 'Customer updated successfully']);
    } else {
        errorResponse(404, 'Customer not found or no changes made');
    }
}

// ─────────────────────────────────────────────
// DELETE — remove a customer
// Endpoint: DELETE /api/customers.php?id=5
// ─────────────────────────────────────────────
function deleteCustomer($conn, $id) {
    $stmt = mysqli_prepare($conn, "DELETE FROM customers WHERE id = ?");
    mysqli_stmt_bind_param($stmt, 'i', $id);
    if (mysqli_stmt_execute($stmt) && mysqli_stmt_affected_rows($stmt) > 0) {
        http_response_code(200);
        echo json_encode(['success' => true, 'message' => 'Customer deleted successfully']);
    } else {
        errorResponse(404, 'Customer not found');
    }
}

// ─────────────────────────────────────────────
// Helper: send a JSON error response
// ─────────────────────────────────────────────
function errorResponse($code, $message) {
    http_response_code($code);
    echo json_encode(['success' => false, 'message' => $message]);
}

Step 3 — Test Your API

You cannot test POST, PUT, and DELETE from a browser URL bar — browsers only send GET requests from the address bar. You need a tool that can send different types of HTTP requests. Here are two options:

Option A: Test in your browser (GET only)

Your GET endpoints work immediately from a browser. With XAMPP running, open these URLs to verify your API is working before testing anything else:

Open in browser — test GET endpoints immediately

# Get all active customers
http://localhost/your-project-name/api/customers.php

# Get customer with ID 1
http://localhost/your-project-name/api/customers.php?id=1

If your API is working, you will see raw JSON in your browser window. It may look messy — install the “JSON Formatter” browser extension (free on Chrome and Firefox) and it will display it as a nicely formatted, colour-coded tree.

Option B: Test with Postman (all methods)

Postman is the industry-standard tool for testing APIs. Download it free from postman.com. Here is how to test each endpoint:

MethodURLBody (JSON)Expected Result
GETlocalhost/project/api/customers.phpNoneJSON array of all active customers
GETlocalhost/project/api/customers.php?id=1NoneJSON object of customer #1
POSTlocalhost/project/api/customers.php{“name”:”Test User”,”email”:”test@example.com”,”phone”:”07700900000″,”plan_id”:1}{“success”:true,”id”:N}
PUTlocalhost/project/api/customers.php?id=N{“name”:”Updated Name”,”email”:”updated@example.com”,”phone”:”07700900001″,”plan_id”:2}{“success”:true,”message”:”Customer updated successfully”}
DELETElocalhost/project/api/customers.php?id=NNone{“success”:true,”message”:”Customer deleted successfully”}

Setting up Postman for POST and PUT requests

  1. Open Postman and click New → HTTP Request
  2. Select POST from the method dropdown
  3. Enter your URL: http://localhost/your-project/api/customers.php
  4. Click the Body tab
  5. Select raw and then JSON from the dropdown
  6. Paste your JSON: {"name":"Test User","email":"test@example.com","plan_id":1}
  7. Click Send and check the response

Interactive API Tester Simulator

See what your API will return for different requests — try each endpoint below:

⚡ API Endpoint Simulator

Response
Click "Send →" to simulate an API request

Step 4 — Call Your API from JavaScript (for React or Plain HTML)

Once your PHP API is working, calling it from JavaScript is straightforward using the fetch() function. This is how a React component or a plain HTML page would get data from your PHP API:

JavaScript fetch() — call your PHP API from any frontend

// ── GET all customers ──────────────────────────────────
fetch('http://localhost/your-project/api/customers.php')
  .then(res => res.json())
  .then(customers => {
    customers.forEach(c => console.log(c.name, c.plan_name));
  });

// ── POST — create a new customer ──────────────────────
fetch('http://localhost/your-project/api/customers.php', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name:    'Sarah Jones',
    email:   'sarah@example.com',
    phone:   '07700900123',
    plan_id: 2
  })
})
.then(res => res.json())
.then(data => {
  if (data.success) {
    console.log('Created customer with ID:', data.id);
  }
});

// ── DELETE a customer ─────────────────────────────────
fetch('http://localhost/your-project/api/customers.php?id=42', {
  method: 'DELETE'
})
.then(res => res.json())
.then(data => console.log(data.message));

Calling your PHP API from Android (Java)

Android Java — HTTP GET request using OkHttp (most common Android HTTP library)

// Add OkHttp to your build.gradle:
// implementation 'com.squareup.okhttp3:okhttp:4.12.0'

OkHttpClient client = new OkHttpClient();

// GET all customers from your PHP API
Request request = new Request.Builder()
    .url("http://10.0.2.2/your-project/api/customers.php")
    // Note: 10.0.2.2 = localhost when running in Android emulator
    // For real devices on same network: use your computer's IP address
    .build();

client.newCall(request).enqueue(new Callback() {
    @Override public void onResponse(Call call, Response response) throws IOException {
        String jsonData = response.body().string();
        // Parse the JSON data here using Gson or org.json
        // JSONArray customers = new JSONArray(jsonData);
    }
    @Override public void onFailure(Call call, IOException e) {
        e.printStackTrace();
    }
});
✅ Your portfolio just got significantly better. Adding “Built a REST API for the [project name] that connects to Android and React clients” to your CV and portfolio description immediately elevates it above the standard “PHP and MySQL management system” description. REST API development is a skill explicitly listed in many junior developer job descriptions.

HTTP Status Codes — Sending the Right Response

A professional API does not just return data — it returns the correct HTTP status code with every response. Status codes are three-digit numbers that tell the client whether a request succeeded or failed, and why. Your code above already uses these correctly — here is what they mean:

CodeMeaningWhen to Use
200 OKSuccess — here is what you asked forSuccessful GET, PUT, DELETE requests
201 CreatedSuccess — a new resource was createdSuccessful POST requests (return the new record’s ID)
400 Bad RequestThe request was malformed or missing required dataMissing required fields, invalid input format
404 Not FoundThe requested resource does not existGET/PUT/DELETE with an ID that has no matching record
405 Method Not AllowedThe HTTP method is not supported by this endpointWhen someone sends PATCH when your API only supports PUT
500 Internal Server ErrorSomething went wrong on the serverDatabase errors, failed queries, unexpected PHP errors

Adapting This API for Your Specific Project

The pattern you just built works for any table in any Codezips project. To add an API for a different resource — bills, doctors, inventory items — follow the same structure with two changes:

  1. Create a new file: api/bills.php (or doctors.php, products.php, etc.)
  2. Replace “customers” with your table name in all the SQL queries, and update the field names to match your actual table columns

SQL Adapt the getAllCustomers() query for the bills table

-- Original customers query:
SELECT c.id, c.name, c.email, c.status, p.plan_name, p.price
FROM customers c
LEFT JOIN internet_plans p ON c.plan_id = p.id
WHERE c.status = 'active'

-- Adapted for bills table:
SELECT b.id, b.amount, b.month, b.status,
       c.name AS customer_name,
       c.email AS customer_email
FROM bills b
JOIN customers c ON b.customer_id = c.id
ORDER BY b.month DESC, c.name ASC

-- Adapted for doctors table (hospital system):
SELECT d.id, d.name, d.specialization, d.phone,
       w.ward_name
FROM doctors d
LEFT JOIN wards w ON d.ward_id = w.id
ORDER BY d.name ASC

Frequently Asked Questions

Do I need Laravel or another framework to build a REST API in PHP?

No — and this guide proves it. Plain PHP can build a perfectly functional REST API with no dependencies, no Composer setup, and no framework to learn. Laravel does make API development easier and more structured for larger projects, but for a student project, a portfolio API, or a first REST API you want to understand completely, plain PHP is the better learning choice. You understand every line of code you write. Once you understand the concepts from this guide, learning Laravel’s API scaffolding takes a fraction of the time because you already know what problem it is solving.

Why does my browser show a CORS error when I try to call the API from JavaScript?

The CORS error happens when your JavaScript (running on one domain or port) tries to call a PHP API on a different domain or port, and the API has not explicitly allowed it. The fix is in config.php — the lines that start with header("Access-Control-Allow-Origin: *") tell the browser “this API accepts requests from any origin.” If you added these headers and are still getting a CORS error, check: (1) the config.php file is being included at the very top of your API file before any other output, (2) there is no whitespace or HTML output before the headers are sent, and (3) your browser is not caching a previous response — try an incognito window.

Is this API secure enough for a real project?

The code in this guide uses prepared statements which protects against SQL injection — that is the most important security measure. For a student portfolio project or development learning exercise, it is appropriate. For a production API handling real user data, you should additionally implement: API key authentication (so only authorised clients can call the API), HTTPS (so data is encrypted in transit), rate limiting (to prevent abuse), and input validation more thorough than what is shown here. For learning and portfolio purposes, what is shown here demonstrates professional awareness of security through the use of prepared statements, which is the right starting point.

How do I connect this API to a React frontend?

In a React component, use the fetch() function (or the Axios library) inside a useEffect() hook to call your PHP API when the component loads. Store the returned JSON in React state using useState(). The fetch() example earlier in this guide shows the exact syntax. The key thing to get right: React runs in the browser, and your PHP API runs on localhost — make sure CORS headers are set in your config.php (they are in the code above), and use the correct localhost URL when React is running in development mode.

How do I make my API accessible from a real Android device (not just the emulator)?

In the Android emulator, 10.0.2.2 automatically routes to your development machine’s localhost — so that works out of the box. For a real Android device, the phone and your computer need to be on the same WiFi network. Then, find your computer’s local IP address (on Windows: ipconfig in Command Prompt, look for IPv4 Address, usually 192.168.x.x) and use that IP in your Android app’s URL instead of localhost. For example: http://192.168.1.15/your-project/api/customers.php. Make sure your computer’s firewall is not blocking port 80 on local network connections.

How should I add this REST API to my portfolio or CV?

Add it to your GitHub repository’s README under a “REST API” section with the endpoint list and example responses. On your CV under the project entry, add a bullet point: “Extended the system with a RESTful JSON API exposing CRUD endpoints for customer management, accessible from any HTTP client including mobile apps and React frontends.” On your portfolio website, if you have deployed the API live, add the live API URL so recruiters can actually call it and see the JSON response — this is genuinely impressive and very few student portfolios include a working live API link.


What to build next — go further with AI

You have a working REST API. The natural next step is adding an AI feature to it — for example, a POST /api/chat.php endpoint that accepts a user question and returns an AI-generated answer using the OpenAI API. That is essentially the same pattern you just learned, with one extra step: forwarding the request to OpenAI and returning the response as JSON. Read our ChatGPT chatbot tutorial to see exactly how this works.

Read: How to Add a ChatGPT Chatbot to Any PHP Website →

Related Tutorials on Codezips

Last updated: April 2026. PHP code tested on PHP 8.2 with XAMPP. REST API concepts and HTTP status codes referenced from RFC 9110 and the REST API Tutorial. Android OkHttp version verified April 2026.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top