What is the correct JSONAPI way to post multiple related entities in a single request?

Viewed 1127

At some point in my hypothetical app, I want to create multiple related entities of different types in a single request, for efficiency sake. In the example below I serialize the request in a way that it contains the data about the new User as well as its related Avatar.

// POST /api/users
{
    data: {
        attributes: { ... },
        type: 'user',
        relationships: {
            avatar: {
                data: {
                    attributes: { ... }
                    type: 'avatar',
                }
            }
        }
    }
}

The question is, what would be the correct/recommended way (if there's any) to do that in JSONAPI?

2 Answers

Creating or updating multiple resources in a single request is not supported by JSON:API spec yet. However there is a proposal for an Atomic Operations extension for the upcoming v1.1 of the spec.

But in most cases such a feature is not required for efficiency. You might even cause more load to the server by bundling multiple create or update requests into one. Doing multiple requests in parallel is cheap with HTTP/2 nowadays.

It might not be as performant as doing it with one requests if the operations depend on each other (e.g. must await a post to be created before a comment for this post could be created). But in that case atomic transactions are also a strong requirement. That's the main driver behind that extension.

So to answer your question:

  • It's currently not supported in JSON:API spec.
  • There is a good chance that it will be supported in the next version (v1.1) by an extension.
  • If efficiency is the only reason you are looking for such a feature, you might not need it at all.

Since it is common, more over may times encouraged to decouple REST API resources from internal representations, there is no recommendation that would suggest against defining a specific 'virtual' endpoint, where the attributes of that resource in turn would become attributes of two or more different resources under different endpoints.

It may not solve your problem, if you want such feature in general, but if this is only needed for some resource combinations, you can always make a dedicated endpoint for a resource which incorporates all attributes of all related resources.

In your case it could be something like:

// POST /api/users_with_avatar
{
  data: {
    attributes: {
      "user_attribute_1": "...",
      "user_attribute_2": "...",
      "user_attribute_3": "...",
      "avatar_attribute_1": "...",
      "avatar_attribute_2": "..."
    },
    type: 'user-with-avatar'
  }
}
Related