getredash/redash · error
Please use a user API key.
Error message
Please use a user API key.
What it means
Raised by QueryResource.post (the query execution/result-job endpoint) in redash/handlers/queries.py when the request authenticates with a query-scoped API key (is_api_user()). Executing or refreshing queries requires a user API key because only a real user can hold modify permissions.
Source
Thrown at redash/handlers/queries.py:461
self.record_event({"action": "fork", "object_id": query_id, "object_type": "query"})
return QuerySerializer(forked_query, with_visualizations=True).serialize()
class QueryRefreshResource(BaseResource):
def post(self, query_id):
"""
Execute a query, updating the query object with the results.
:param query_id: ID of query to execute
Responds with query task details.
"""
# TODO: this should actually check for permissions, but because currently you can only
# get here either with a user API key or a query one, we can just check whether it's
# an api key (meaning this is a query API key, which only grants read access).
if self.current_user.is_api_user():
abort(403, message="Please use a user API key.")
query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
require_access(query, self.current_user, not_view_only)
parameter_values = collect_parameters_from_request(request.args)
parameterized_query = ParameterizedQuery(query.query_text, org=self.current_org)
should_apply_auto_limit = query.options.get("apply_auto_limit", False)
return run_query(parameterized_query, parameter_values, query.data_source, query.id, should_apply_auto_limit)
class QueryTagsResource(BaseResource):
def get(self):
"""
Returns all query tags including those for drafts.
"""
tags = models.Query.all_tags(self.current_user, include_drafts=True)
return {"tags": [{"name": name, "count": count} for name, count in tags]}
View on GitHub (pinned to ca79fe988d)
Solutions
- Use your personal user API key (found in the user profile Settings page, or via the users API).
- If embedding read-only access was the goal, use the query result endpoint (GET latest result) which permits query API keys.
- Store the key under a distinct env var (e.g. REDASH_USER_API_KEY) to avoid mixing key types.
Example fix
# before
headers = {'Authorization': 'Key <query-scoped-api-key>'}
client.post('/api/queries/123/refresh', headers=headers)
# after
headers = {'Authorization': 'Key <user-api-key>'}
client.post('/api/queries/123/refresh', headers=headers) Defensive patterns
Strategy: validation
Validate before calling
# check key type: query keys fail execution, user keys work
who = client.get('/api/session')
assert not who.get('is_api_user', False) or 'query' not in key_scope Try / catch
try:
client.post(f'/api/queries/{qid}/refresh', headers=h)
except HTTPError as e:
if e.response.status_code == 403 and 'user API key' in e.response.text:
h['Authorization'] = f'Key {os.environ["REDASH_USER_API_KEY"]}'
client.post(f'/api/queries/{qid}/refresh', headers=h)
else:
raise Prevention
- Keep separate env vars for user keys vs query keys.
- Use query-scoped keys only for read endpoints (latest result, widgets).
When it happens
Trigger: POST /api/queries/<id>/results (or /refresh) using the API key shown on a query's sharing dialog instead of the user profile API key.
Common situations: Copy-pasting the wrong key from the UI (query key vs personal key); CI jobs configured with a share key attempting to trigger executions; scripts written against read-only endpoints later upgraded to trigger execution with the same key.
Related errors
- You do not have access to data source: %s.
- You do not have access to query id %s.
- Python query helpers require a current user.
- Failed getting schema
- Public URLs are disabled.
AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28).
Data as JSON: /api/errors/38d678c9355bd367.
Report an issue: GitHub.