0

Let's say I have two objects: Student and Homework. Homework has Student as fk:

CREATE TABLE student (
    id serial PRIMARY KEY,
    name varchar(100)
)

CREATE TABLE homework (
    id serial PRIMARY KEY,
    topic varchar(255),
    student_id int REFERENCES student(id)
)

Is there any convention for what is the right way to structure the API endpoints for CRUD?
If I want to create a new homework for a student, I could send a json body with student id

{
    "student_id": 1,
    "topic": "topic
}

to POST https://website.com/api/v1/homework.

Or I could send

{
    "topic": "topic
}

to POST https://website.com/api/v1/students/{student_id}/homework and take student id from URL.

In second case I would be sending a POST request with incomplete fields and in first case I would have one extra endpoint (since I would need /students/{id}/homework anyway to fetch particular student's homework.)

estw272
  • 211
  • 5
  • 20

1 Answers1

3

You have two entities Student and Homework. A Homework entity belongs to Student.

So the more semantically correct approach would be:

  • Create Homework Endpoint:

    POST https://website.com/api/v1/students/{student_id}/homeworks/add
    
  • Delete Homework EndPoint:

    DELETE https://website.com/api/v1/homeworks/{homework_id}
    

There are no agreed rules but this is generally a widely followed pattern:

If A owns B, and you want to create a new B entity, your path will be like /A/{A_Id}/B/add.

  • Boilerplate Request:

    POST /ParentEntity/ParentId/ChildEntity/add
    

Now B was created and you have an id associated with it, so you can directly alter B (say for any mutation operation, POST, DELETE, PUT, PATCH).

DELETE /B/{id}

PUT /B{id}

OR

POST /B/{id}/delete

POST /B/{id}/update

(this one is followed by StackOverflow, where your request intention/action is defined in URL suffix instead of being defined by your HTTP method)


Why do we do directly alter B? Why not do something like:

DELETE /A/{Aid}/B/{Bid}

Because /A/{Aid} would be redundant information. Since it is guaranteed that {Bid} would always be unique even though multiple B entities can belong to a single A entity.


Additional References:

You can see the API pattern Stackoverflow has used for their APIs here for any future reference. https://api.stackexchange.com/docs?tab=category#docs

Hackinet
  • 3,252
  • 1
  • 10
  • 22
  • Adding `/delete` to your URI for a `DELETE` request is _definitely not_ a widely accepted pattern. – Evert Feb 14 '22 at 17:47
  • @Evert yep overlooked that. I initially had `POST` for both delete and update. Fixed. Thanks. – Hackinet Feb 14 '22 at 17:53
  • Thank you for detailed answer, what's the point for using `POST .../homework/add` instead of just `POST .../homework`? – estw272 Feb 15 '22 at 01:11
  • It should have been `homeworks` instead of `homework`. My bad. In that case, you will have `{parent}/{parentId}/homeworks/add` and `{parent}/{parentId}/homeworks`. When you use POST for everything, your endpoint suffix tells you the intention in a sense, and if you are doing that then `{parent}/{parentId}/homeworks` would be a GET request that returns a JSON of homeworks on that parentId. – Hackinet Feb 17 '22 at 06:34