0

We have a JSON:API that allows users to CRUD various types of resource objects. We want to introduce an enhancement to our service where a client application can access an object by calling a well-maintained external identifier, without having to directly reference the ID. Does anyone have experience with this?

Use Case:

ID: 1000002 External_ID: hr1234

Currently you'd make the request to URL: GET https://examplefirm.saas.com/api/v1/person/1000002

How can I access ID:1000002 with External_ID:hr1234 without first having to do a lookup?

FamLamb
  • 13
  • 3
  • What do you mean by "lookup"? Did you considered using a filter? Like `/api/v1/persons?externalId=hr1234`? – jelhan Mar 26 '21 at 10:10
  • Ah, thats exactly what I meant. Would the external ID be an attribute or relationship of the object? – FamLamb Mar 26 '21 at 13:26

1 Answers1

0

I would recommend to use filtering for it.

The JSON:API specification is agnostic about the filtering strategy. So you could implement any strategy that fits well for your use case. It only recommends to use the filter query parameter family for filtering (and reserves the query parameter for that purpose).

There is a recommendation document as an attachment to the specification. It describes a simple filtering strategy, which may fit your needs very well. It applies strategies used for other query parameters used in the specification (sort, include and fields) to filter.

The query parameter is constructed as ?filter[KEY]=value. There are good arguments to use the name of an attribute or a path as a key. But you aren't limited to do so. It applies an equal comparison to it.

For you example this would look like ?filter[externalId]=hr1234 assuming that the attribute on the resource containing the external ID is named externalId. If you follow another naming strategy (e.g. underscore or dashes between multiple words), I would recommend to reflect that one in the filtering key as well.

Please have in mind that using filtering to lookup a record by an external ID works differently than a lookup of a resource by ID:

  • It always returns a collection of resources.
  • It does not return a 404 Not Found, if no resource with that external ID exists. Instead an empty collection is returned.
  • It may return more than one resource, if the external ID is not guaranteed to be unique.

If this is acceptable for you, using filtering is the simplest approach. If not, you could consider to have special endpoints to lookup a resource by an external ID. For example you may have a /api/v1/persons-by-external-id/:externalId endpoint, which returns the JSON:API resource either directly or does a temporary redirect to /api/v1/persons/:idForPersonWithExternalId. As JSON:API specification is agnostic about URL design this would be fine from specification perspective. But as it is way less common I would expect issues with existing client-side libraries.

jelhan
  • 6,149
  • 1
  • 19
  • 35
  • Thanks again. Does the external ID need to be an attribute on the resource object? How might this work if I wanted to create a new object with an external ID? – FamLamb Mar 26 '21 at 14:17
  • No need to have the external ID as an attribute. A filter criteria can be totally independent of any resource field. I'm not sure what you mean by the second question. Are you wondering how to migrate when the record referencced by external ID gets an additional JSON:API resource later? Like a migration strategy? – jelhan Mar 26 '21 at 19:10