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 first case I would be sending a POST request with incomplete fields and in second case I would have one extra endpoint (since I would need /students/{id}/homework
anyway to fetch particular student's homework.)
CodePudding user response:
I'll recommend the second approach:
A homework can't exist without an associated student.
Best Practices:
What are best practices for REST nested resources?.
And Resource Raming:
https://restfulapi.net/resource-naming/
CodePudding user response:
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}/homework/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