APIs and automation
REST APIs that answer with the wrong status code, request shapes that changed between versions, authentication transports that silently differ, and clients that fail before a request leaves the machine.
- curl exits 3 on a Jenkins API call: square brackets in tree= are not URL-safe
A Jenkins REST query that works pasted into a browser dies in the shell with curl exit code 3 and no request on the wire. Why the tree= filter's brackets are the cause, and how -G --data-urlencode fixes it for good.
- MCP server dies at startup after the mcp package resolves to 2.0.0
A working stdio MCP server suddenly fails to start because its dependency spec says mcp>=0.9.0 and the resolver picks 2.0.0, which removed Server.list_tools(). Pin the SDK, and check the client side too.
- gpsoauth returns BadAuthentication on a 2FA Google account (app passwords do not help)
perform_master_login fails with BadAuthentication even with an app password. The working path is the oauth_token cookie from accounts.google.com/EmbeddedSetup — and you can capture that HttpOnly cookie over CDP instead of digging in DevTools.
- Graylog 7 API: POST /api/streams returns 400 "entity cannot be null"
The stream creation payload changed in Graylog 7: the stream object must be wrapped in an entity envelope. Also, the root admin account cannot hold an API token, which breaks scripted setups in a second, less obvious way.
- MusicBrainz ws/2 returns 503 "currently busy", and the track lengths you need are often missing
Lookups against the MusicBrainz web service fail intermittently with HTTP 503, and the releases that do come back frequently carry no track durations. How to set a compliant User-Agent, retry sanely, and fill the gaps from a second source.
- Teams incoming webhook returns HTTP 200 but no message appears
Office 365 connector webhooks on *.webhook.office.com are retired: they accept your POST, answer 200 and silently drop it. The response headers prove it. Migrate to a Power Automate Workflows webhook and an Adaptive Card payload.
- Reading and writing MediaWiki pages from a script: action=raw and the two-token login
Fetching a wiki page with an HTTP client can silently return Recent Changes instead of the article, and editing needs two different tokens in the right order. Both fixes, plus the credential-file trap that broke my first attempt.
- Redmine REST: POST /uploads.json returns 404, and the API key only works in the query string
A documented Redmine endpoint answering 404 means attachments cannot be uploaded through the API at all, and the same key that authenticates in the query string is rejected as a header. How to prove both in three curl calls and what to build instead.
- Gmail throws away your <style> block: generating HTML mail that survives the client
A generated report mail renders perfectly in a browser and arrives in Gmail as an unstyled slab of text. Why the stylesheet never reaches the renderer, how to inline what matters, and how to build the multipart draft the Gmail API accepts.
- When an MCP wrapper hides API fields: set Redmine parent, due date and estimate over REST
create_issue and update_issue in a Redmine MCP wrapper expose only a handful of fields, so parent_issue_id, due_date and estimated_hours are unreachable. The REST API supports all of them — including the query-string API key the docs bury.