Integrating: a whole zoo of conventions on both sides of req/res. Auth methods (header, bearer, in-payload), signing (cf of ordered field concatenation), excessive encodings and/or encryption, success reports. Underconstrained and incomplete descriptions (does 200 always imply {status:"success",…}?). Examples with misleading bogus data in requests and empty responses, or non-reproducibility. Either no testing endpoints, or test.example.com works different from api.example.com. Hateoas continuations from json to html implying you’re a browser. Inconsistencies in call schemes which prevent factoring out most of the above into a single interface.<p>A special place in hell for APIs with multi-step setups for an access token (get jwt to get jwt which expires in few minutes but ofc cannot be renewed in advance), multi-step setups for a request envelope, then a cryptic payload, then polling (not too often!) for “ready” identifiers (which disappear once fetched, so please cache not-yours ones), then a separate request for fetching a response by identifier, deleted once fetched. Telcos and banks <i>love</i> this bullshit.<p>-<p>Building: needing to take various platforms and traditions into account (e.g. some php shops just don’t understand what long-poll or jsonl/ndjson streaming is and have a higher chance of hitting the auth wall for days). Webhook-based messaging requires valid domain names in development or setting up a complex local infrastructure. Overall boring prologues and epilogues for api calls in standard http libraries (try, rate, auth, parse params/body, validate, 2 lines of actual code, catch, decide if error is worth 500 or 4xx with a message, log details, report back). Testing with curl with auth/signing enabled just sucks.