We generally try to keep data together, so any business information that the main process logic is dependent on should be in the payload. We generally expect that the main body content will be passed through end to end unaltered, but headers can be both added to and manipulated en-route.
So where practical, put as much of the data in the body of the request.
Headers are useful for meta-data, that is information about the payload, but not intrinsic to the data payload itself. This might include information about the caller or current state of the calling context. Headers are useful to target in this regard because a global filter on the client side or the server side can resolve and inject the necessary information without affecting the payload. This means we can de-couple the business payload from the metadata about the environment.
Sometimes we can optimise a process by exposing some main data elements in the header, as headers can be processed without accessing the main body content, however keep in mind that URL parameters and other HTTP Headers will be exposed to and included in many logs, at the client and server ends as well as at any intermediary points like firewalls.
HTTP GET requests of course differ because they have no body content. Instead sometimes we can engineer the route (Path) to represent some information about the request, other times the data may be passed as parameters in the query.
Some frameworks implement specific conventions or rules that govern strict criteria for the body or the path or query elements of the request, in these cases we are sometimes forced to use headers if we need to pass additional information that the framework may not understand, but our business logic will, headers are a great way to overcome the limitation of some frameworks in this way.
If you can not explicitly explain why a data element should NOT be in the body, then you should leave it in the body. The standard headers like
Accept really highlight the type of data we are talking about here, these headers contain information about the type of request, the expected response and the credentials for the caller, these are not directly business domain concepts, though they might map to or be useful to drive some business logic they exist outside of the main business domain.
Authorization is a little bit special, our apps usually need it, but this header is generally processed by a sub-routine of the hosting architecture (Middleware), your business process would not normally access this header directly, your code would normally consult the HTTP Runtime Framework to resolve the value from the header for us.
- But it is still better suited to be a header, because it exists outside of the Business Domain, the same authorization header would be used for many different requests for instance.