Home > Enterprise >  REST API POST: passing foreign key in url vs json body
REST API POST: passing foreign key in url vs json body

Time:02-15

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

  • Related