To summarize: send a 202 for the initial request, redirecting to a job URL. The client polls on the job URL, which returns 200 with progress information until it's done, when it returns a 303 redirecting to the final output.
One particular problem spot is that many http libraries automatically follow the 303 redirect, and some even follow the 202 redirect.
I definitely think we would have been better off just putting status and final location information as JSON attributes in the body rather than putting it in HTTP response codes and Location headers. Non-standard, but much less confusing for our customers.
And all computations can be modeled as Universal Turing Machines at some level. That doesn't mean it's the most useful level at which to analyze the semantics of what you are trying to accomplish.
The short answer is that there is really no good general purpose way to deal with asynchronous communication in a "restful" HTTP API. All solutions have major drawbacks. This is one of the biggest shortfalls of rest/http in my experience. People tend to switch to other protocols to address these use cases (this is a common reason for adopting message bus infrastructure like Kafka as part of a SOA).
DigitalOcean's API does this in quite a few spots [1] - it calls the async jobs "actions", but they signal completion of jobs performed on base objects.
To summarize: send a 202 for the initial request, redirecting to a job URL. The client polls on the job URL, which returns 200 with progress information until it's done, when it returns a 303 redirecting to the final output.
One particular problem spot is that many http libraries automatically follow the 303 redirect, and some even follow the 202 redirect.
I definitely think we would have been better off just putting status and final location information as JSON attributes in the body rather than putting it in HTTP response codes and Location headers. Non-standard, but much less confusing for our customers.