Skip to content

Instantly share code, notes, and snippets.

@rtoal
Last active September 24, 2016 19:22
Show Gist options
  • Save rtoal/4a79975b5c09b84bc2c92af6b5b2dbcb to your computer and use it in GitHub Desktop.
Save rtoal/4a79975b5c09b84bc2c92af6b5b2dbcb to your computer and use it in GitHub Desktop.
A general question about bulk operations in RESTful APIs

An API Design Choice

Let's say we have an API endpoint

POST /customers

which creates a customer given a suitable JSON document and returns a 201 CREATED on success.

Now suppose we want to create 100,000 or more customers in a batch. Customer creation takes a bit of time, so the response to this request, if successful, will be a 202 ACCEPTED. The HTTP RFC recommends also returning a "pointer to a status monitor" which can be used, perhaps, in a GET request which will return a document containing fields such as:

   {
      "total_customers_requested": num,
      "number_created": num,
      "number_failures": num,
      "completed": bool
   }

Now the question is how should we structure and name the endpoints.

Option 1 - Fire and forget

Since only a customer is a domain object, we let POST /customers check its request and if only one customer is present, creates and returns a 201; if more, it spawns a task and returns a 202 without any additional information.

Option 2 - The callback

Just like option 1, but the request contains the uri (webhook) that our job can write status and/or completion info to.

Option 3 - Introduce a status resource only for querying

As in option 1, POST /customers switches on its request type (one vs. many), but if spawning a task it returns a 202 ACCEPTED and a job id. The job id is used to make the status request: GET /customer_job_statuses/874372.

Option 4 - Jobs are resources

Here we leave the existing POST /customers alone and treat batch jobs as a first-class resource. To create multiple customers we create a job: POST /customer_jobs with the customers to create, and to read the status we simply do GET /customer_jobs/874372.

So, four options, and perhaps you can think of more. I don't care what is the "most RESTful" since pragmatism and best practices should guide the decision. Which of the options exhibit the best design? Which would you prefer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment