Errors and retries
API failures return an HTTP status and JSON body:
{
"message": "Feedback not found.",
"statusCode": 404
}This example uses Accept-Language: en. message is display text and varies by language. Validation errors may include field paths such as title: ...; issueIds: .... The REST API does not provide a separate stable string error code.
HTTP status handling
| Status | Typical cause | Action |
|---|---|---|
400 | Invalid UUID, field, query, or PR URL; feedback from another app | Correct the input |
401 | Missing session, expired/revoked/invalid token, Bearer used for token management | Check authentication |
403 | Not the owner, wrong app token, missing scope, disallowed Origin | Check app, scope, and origin |
404 | Feedback, request, or token not found in the app | Recheck IDs and app |
409 | Same request ID with different content, or a different PR already linked | Inspect existing work |
413 | JSON body exceeds 64 KiB | Reduce the body |
429 | Too many requests | Wait for Retry-After seconds |
500 | Server failure | Retry with a bounded delay |
The first failed check determines the response. For example, a malformed Bearer mutation without Origin may return 403 before token validation.
Rate limits
The default automation limit is 120 requests per minute per IP, shared by feedback, change requests, and token management. Changing apps or tokens does not reset that IP's allowance. Deployment and proxy settings may impose additional limits.
A 429 response provides the remaining wait in seconds:
HTTP/1.1 429 Too Many Requests
Retry-After: 28
Content-Type: application/jsonSpace out polling and fetch only the pages you need. Avoid repeatedly sending identical requests in a tight loop.
Missing responses
The server may have completed a request even when a connection drops or the client times out.
| Operation | Retry rule |
|---|---|
| Read feedback, requests, or tokens | Retry the same request |
| Create change request | Keep the same clientRequestId and body |
| Link PR | Keep the same request ID and PR URL |
| Revoke token | Retry the same token ID |
| Issue token | Do not retry automatically; each request issues another token |
Creation uses JSON clientRequestId, not an Idempotency-Key header. The same app/creator/key with different content returns 409. Retain the ID together with its body until the outcome is known.
Honor Retry-After for 429. Use bounded exponential backoff with jitter for temporary network/server errors. Resolve the cause before repeating 400, 401, 403, 404, or 409 requests.
Common issues
403 on another app owned by the same account
Tokens belong to one app. Issue a token for the target app and match OPENTESTER_APP_ID.
Writes work but reads fail
Scopes are independent. Feedback reads need feedback:read; change request reads need work-items:read.
Requests from the docs domain fail
The docs site is static. Use the API base URL for automation, and the signed-in console's Origin for web-session requests such as token management. See authentication.
Feedback remains open after linking a PR
This is expected. Linking stores the PR URL on the change request. Review and change feedback status separately in the console.