Summary
Registering a dynamic webhook via POST /rest/api/3/webhook returns an unhandled HTTP 500 (x-failure-category: FAILURE_ORIGIN, text/html, empty body) when the request is authenticated with an OAuth 2.0 service-account access token obtained via the client_credentials (2LO) grant; even though the token carries the required manage:jira-webhook scope. The identical request with a 3LO (user-authorized) OAuth 2.0 token succeeds. Either service-account tokens should be supported for this endpoint, or the API should return a documented 4xx (as it already does for other unsupported credential types) instead of a 500.
Environment
- App: OAuth 2.0 integration (not Connect/Forge).
- Credential under test: 2LO service account; token minted via
POST <a href="https://auth.atlassian.com/oauth/token" rel="noopener nofollow noreferrer" target="_blank">https://auth.atlassian.com/oauth/token</a> with grant_type=client_credentials, audience=api.atlassian.com. - Access-token claims (decoded):
"<a href="https://atlassian.com/3lo" rel="noopener noreferrer" target="_blank">https://atlassian.com/3lo</a>": false, "<a href="https://atlassian.com/authProfile" rel="noopener noreferrer" target="_blank">https://atlassian.com/authProfile</a>": "oauth.adminhub.serviceAccount2LO", sub: "<client_id>@clients", scope: "manage:jira-webhook read:field:jira read:jira-user read:jira-work write:jira-work".
Steps to reproduce
- Mint a service-account token:
-H 'Content-Type: application/json' \
-d '{"grant_type":"client_credentials","client_id":"<SERVICE_ACCOUNT_CLIENT_ID>","client_secret":"<SECRET>","audience":"api.atlassian.com"}'
(Returns an access token with manage:jira-webhook, 3lo=false, authProfile=oauth.adminhub.serviceAccount2LO.) - Register a webhook with that token:
curl -i -X POST \
-H 'Authorization: Bearer <SERVICE_ACCOUNT_ACCESS_TOKEN>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
Expected
Either (a) the webhook is registered and webhookRegistrationResult[].createdWebhookId is returned, or (b) a documented 4xx explaining the credential type isn't supported — e.g. the way a scoped/API-token request returns 403 {"errorMessages":["Only Connect and OAuth 2.0 apps can use this operation"]}.
Actual
HTTP/1.1 500
content-type: text/html;charset=UTF-8
x-failure-category: FAILURE_ORIGIN
x-arequestid: dfe789acfec52b94a3a0fda99caab303
(empty body)
No JSON error, no errorMessages; impossible to handle programmatically. Please check the origin logs for request id dfe789acfec52b94a3a0fda99caab303.
Behaviour across credential types on the same endpoint (this is the core of the report)
| Credential | Result |
|---|
OAuth 2.0 3LO (user-authorized), manage:jira-webhook | ✅ 200, createdWebhookId returned |
| Scoped API token | ⛔ 403 — clean, documented (Only Connect and OAuth 2.0 apps…) |
OAuth 2.0 2LO service account (client_credentials), manage:jira-webhook | ❌ 500 FAILURE_ORIGIN, empty HTML body |
Questions / ask
- Are dynamic webhooks (
/rest/api/3/webhook) supported for OAuth 2.0 service-account (client_credentials) tokens? Service accounts are offered as a way for apps to act without a user, yet dynamic webhooks appear to require a per-user owner ("N webhooks per app per user"). - If supported → the 500 is a server-side bug; please investigate via the request id above.
- If not supported → please return a documented 4xx (like the scoped-token case) and note the limitation in the webhooks docs, so integrators can detect it and guide users to a 3LO connection instead of hitting an opaque 500.