Skip to content

Chapter 3.2: Creating Your First API Endpoint

Time to learn: 30 minutes


1. Endpoint: A Docking Port for Data

Imagine our API is a space station. An Endpoint is a specific docking port designed for a certain type of ship.

  • Port No. 1 — for cargo ships (data about planets).
  • Port No. 2 — for research probes (data about missions).
  • Port No. 3 — for passenger shuttles (data about astronauts).

Each endpoint is a unique URL that is responsible for a specific operation with a specific resource.

💡 Space Analogy: GET /spaceships is the command "Mission Control → Station: Report the list of all docked ships." This endpoint returns a collection of resources.


2. Creating the "Space Fleet"

Since we don't have a database yet, let's create a "simulation"—a simple list of spacecraft in the form of a Python dictionary.

Open main.py and add this code before the app definition:

# main.py

# Step 1: Create a database simulation
db_spaceships = {
    1: {
        "name": "Voyager-1",
        "type": "Probe",
        "launch_year": 1977,
        "status": "Active"
    },
    2: {
        "name": "Hubble Space Telescope",
        "type": "Telescope",
        "launch_year": 1990,
        "status": "Active"
    },
    3: {
        "name": "ISS",
        "type": "Station",
        "launch_year": 1998,
        "status": "In Orbit"
    }
}

# ... app = FastAPI() code goes here
This is our "registry of spacecraft" that we will be working with.


3. First Endpoint: The List of Ships

Now let's create an endpoint that will return our entire fleet.

Add this code to main.py after the @app.get("/") block:

# main.py

# ... code with db_spaceships, FastAPI, app, and read_root() ...

@app.get("/spaceships")
def get_spaceships():
    """
    Returns a list of all spacecraft in the registry.
    """
    return db_spaceships

  • @app.get("/spaceships"): We have created a new route. Now, GET requests to the /spaceships URL will be handled by the get_spaceships function.
  • return db_spaceships: FastAPI will automatically convert the Python dictionary into a valid JSON response.

4. Checking the New Docking Port

If your uvicorn server is still running with the --reload flag, it has already reloaded and is ready to go. If not, start it again:

uvicorn main:app --reload

Step 1: Check in the browser

Open http://127.0.0.1:8000/spaceships in your browser. You should see the full list of your ships in JSON format:

{
  "1": {
    "name": "Voyager-1",
    "type": "Probe",
    "launch_year": 1977,
    "status": "Active"
  },
  "2": {
    "name": "Hubble Space Telescope",
    "type": "Telescope",
    "launch_year": 1990,
    "status": "Active"
  },
  "3": {
    "name": "ISS",
    "type": "Station",
    "launch_year": 1998,
    "status": "In Orbit"
  }
}

Step 2: Check in the auto-documentation

Navigate to http://127.0.0.1:8000/docs. You will see that a new section for the GET /spaceships endpoint has appeared in the documentation. You can click "Try it out" and "Execute" to test it right from there!


5. Endpoint with a Parameter: Data on a Specific Ship

What if we only need data about "Voyager-1"? For this, we will create an endpoint with a path parameter.

Add this code to main.py:

# main.py

# ... rest of the code ...

@app.get("/spaceships/{ship_id}")
def get_spaceship(ship_id: int):
    """
    Returns data about a specific spacecraft by its ID.
    """
    return db_spaceships.get(ship_id)

  • "/spaceships/{ship_id}": The curly braces {} tell FastAPI that ship_id is a variable that will be passed from the URL.
  • ship_id: int: This is a type hint. FastAPI will automatically check that the passed ID is an integer. If someone requests /spaceships/voyager, FastAPI will return a 422 Unprocessable Entity validation error. This is magic!

Check:

Open http://127.0.0.1:8000/spaceships/2. You should get the data only for the Hubble telescope. And if you open http://127.0.0.1:8000/spaceships/99 — you will get null, as no such ship exists.


Review Quiz

1. An endpoint in an API is...

2. What does the `@app.get("/users")` decorator do?

3. What does the notation `"/items/{item_id}"` in a path mean?

4. Why is the type hint `ship_id: int` needed in the function?

5. If you request `/spaceships/abc` and FastAPI expects an `int`, what will happen?


🚀 Chapter Summary:

You have successfully created two "docking ports" on your API space station:

  • 🛰️ One to get a list of all ships (/spaceships)
  • 🔭 A second to get data about a specific craft (/spaceships/{ship_id})

You have also seen the power of FastAPI's automatic type validation, which protects your API from invalid requests.

The navigation system is configured! In the next chapter, we will create "blueprints" for our spacecraft using Pydantic to make our API even smarter and more reliable.

📌 Checkpoint:

  • The uvicorn server is running.
  • The URL http://127.0.0.1:8000/spaceships returns a JSON with the list of ships.
  • The URL http://127.0.0.1:8000/spaceships/1 returns the data for "Voyager-1".
  • The URL http://127.0.0.1:8000/docs shows two new endpoints.

⚠️ If you have errors:

  • 404 Not Found: Check that the URL is spelled correctly in the browser and in the @app.get(...) decorator.
  • Code Error: Carefully check the syntax, especially indentation in Python and commas in the dictionary.