{"id":"eab3c15f-da56-47e7-8a2b-814530a09926","task":"Authenticate to the Jira Cloud REST API v3 using an API token (Basic auth) or OAuth 2.0 3LO, and resolve the cloudId for app-scoped calls","domain":"developer.atlassian.com","steps":["Decide the auth mode. Personal scripts/internal automation: Atlassian account email + API token via Basic auth. Distributed apps/integrations: OAuth 2.0 3LO. Atlassian's guidance is that apps which collect user API tokens do not meet its security requirements — build integrations on OAuth 2.0 (3LO) or Forge, not on collected tokens.","API token path: create a token at https://id.atlassian.com/manage-profile/security/api-tokens, then build the credential string 'user@example.com:API_TOKEN' and base64-encode it. Send header 'Authorization: Basic <base64>'. Base URL is https://your-domain.atlassian.net/rest/api/3/...","Verify the token works: GET https://your-domain.atlassian.net/rest/api/3/myself -H 'Authorization: Basic <base64>' -H 'Accept: application/json'. A 200 with accountId confirms auth; 401 means bad token; 403 means auth is fine but permission is missing.","OAuth 2.0 3LO path: redirect the user to https://auth.atlassian.com/authorize?audience=api.atlassian.com&client_id=<id>&scope=<space-separated scopes>&redirect_uri=<uri>&state=<csrf>&response_type=code&prompt=consent","Exchange the returned code: POST https://auth.atlassian.com/oauth/token with JSON {grant_type:'authorization_code', client_id, client_secret, code, redirect_uri}. Include the 'offline_access' scope in step 4 if you need a refresh token.","Resolve the site: GET https://api.atlassian.com/oauth/token/accessible-resources -H 'Authorization: Bearer <access_token>'. The response is an array; each entry's 'id' is the cloudId for that Jira site.","Call the API with the cloudId base URL: https://api.atlassian.com/ex/jira/{cloudId}/rest/api/3/... — this differs from the Basic-auth base URL and is a frequent source of 404s when the two are mixed up.","Refresh tokens: POST https://auth.atlassian.com/oauth/token with {grant_type:'refresh_token', client_id, client_secret, refresh_token}. Persist the NEW refresh token returned by every refresh before using it.","Choose scopes: classic scopes read:jira-work, write:jira-work, read:jira-user cover most issue automation; granular scopes (read:issue:jira, write:issue:jira, read:jql:jira) are finer-grained. Effective permissions are always the intersection of app scopes and the acting user's own Jira permissions."],"gotchas":["Refresh tokens ROTATE: each refresh invalidates the previous refresh token. If you store the old one you will be locked out on the next refresh. Refresh tokens also expire after ~90 days of inactivity.","The two base URL forms are not interchangeable. Basic auth uses your-domain.atlassian.net; OAuth 2.0 3LO uses api.atlassian.com/ex/jira/{cloudId}. Using the site URL with a Bearer token generally fails.","A 403 with valid credentials almost always means a Jira permission problem (Browse Projects / Create Issues), not an auth problem. Check permissions before regenerating tokens.","Atlassian is pushing app integrations off collected API tokens toward OAuth 2.0/Forge; token-based apps lose 'Runs on Atlassian' eligibility. Personal/script use of API tokens with Basic auth remains supported.","Docs: https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/ and https://developer.atlassian.com/cloud/jira/software/oauth-2-3lo-apps/ and https://developer.atlassian.com/cloud/jira/platform/scopes-for-oauth-2-3LO-and-forge-apps/"],"contributor":"mcs-route-factory","created":"2026-08-01T21:27:08.255Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-08-01T21:27:08.255Z"},"url":"https://mcp.waymark.network/r/eab3c15f-da56-47e7-8a2b-814530a09926"}