Including resources during creation

Regarding creating resources, the spec notes:

If a relationship is provided in the relationships member of the resource object, its value MUST be a relationship object with a data member. The value of this key represents the linkage the new resource is to have.

Regarding inclusion, the spec notes:

Note: This section applies to any endpoint that responds with primary data, regardless of the request type. For instance, a server could support the inclusion of related resources along with a POST request to create a resource or relationship.

When I’m creating a new resource and want to created a related resource in the same request, I have to figure out how to link them together. Both resources will not have an ID yet.

So, how should I solve this?

Our system is not designed to persist client-generated IDs. We could adjust it so it would allow them through the API, but would replace them with system-generated IDs. I was not able to tell if this would be in line with the spec.

It is perfectly valid to accept the user defined IDs as part of the compound document and return the representation with final identifiers through your response document.

This introduces an interesting thought if you have multiple resources being created of the same type, there might be ambiguity on how to equate them with your local cache copies. You could use a custom meta field for previous id, less likely useful json object equivalence without the ID fields, or simply never cache the local copies and have the server respond with a fully linked document of resources.

This question does expose an ambiguity on how to address the local copy on user provided IDs when those are only used for document linking.

Perhaps I’ll write up a PR with something for this.

My current approach would be to use UUIDs when referencing existing resources and simple integers (formatted as strings) when referencing included resources that are supposed to be created with the primary resource object.

A solution where the id would be allowed to be typed as a Number seems even more attractive to me (for simplicity of validation). But this approach seems like it could work for us.

Any thoughts regarding that approach?

The spec requires you to use UUIDs to reference user provided IDs. Which I believe in your case would be the resources to be created with the primary resource as well as the primary resource ID if you intend to provide one. If you plan to use a UUID as the existing resource identifier there is no need to assign another value as properly generated UUIDs should be globally unique. Dealing with any extremely unlikely collisions would be a very simple process of replacing the value, but only if a collision is detected.

I highly advise you to step back, rethink your approach, and examine your reasoning to see why the Number type appeals to you, because this is the exact opposite of how I look at a sequential numeric key to be used in an API. Using a Number might make the validation easier, but now your concurrency and unique properties are all suspect from a user provided perspective, as well as the requirements to expire local caches with old temporary values. Like I’ve said previously, just giving you the answer which is below is only part of the goal. I want to help you understand how to think about the APIs to understand the constraints of an APIs design which are not immediately apparent.

If you plan to use UUIDs as the primary ID type, simply use UUIDs for everything.

As always, your advise gave me something to think about and, ultimately, I have to agree with your reasoning again.

After taking a step back, I also realized that there is really no benefit to be had by using a different type of ID. After all, I already know when the user has the intention to create a new record, because they included it. If they didn’t want to create a new record, they would reference an existing one, which is not a task accomplished by inclusion.

I’m glad I was able to help.