{% extends "layouts/settings.html" %} {% comment %} API keys, in the shape contacts/tag_list.html established. The issue form is a modal that opens itself on an error (`open=error`), because issue_key answers a refusal by re-rendering this page at status 400 rather than redirecting, and a dialog that stayed shut would hide the form that produced the message. The message renders inside it, next to the fields it is about. No named action on a row: the only thing you can do to a key is revoke it, and a destructive action is the one thing that must not be the row's obvious button. {% endcomment %} {% load common_extras %} {% block title %}API keys · DemandTrail Messaging{% endblock %} {% block content_wrap %}{% endblock %} {% block content %}
{% if workspaces %} {% modal "issue-key" title="Issue a key" open=error size="lg" %}
{% csrf_token %}
{% if error %}
{{ error }}
{% endif %}
Scopes {% for value, label in scope_choices %} {% endfor %}

Read lists contacts, tags, fields and flows. Write adds creating and updating contacts, tagging, setting field values, starting flows and sending messages. No scope grants channel, member or key management.

{% endmodal %} {% else %} {% comment %} Both gates have to pass to issue a key: organization admin (which the page already required) and manage_api_keys in the target workspace. Saying so is the difference between a fixable state and an empty dropdown. {% endcomment %}
You are an organization admin, but you do not hold the manage_api_keys permission in any workspace, so there is nowhere to issue a key. A workspace admin can grant it.
{% endif %}

Existing keys

{% if rows %}
{% for row in rows %}
{% include "partials/_nav_icon.html" with name="key" icon_size=19 %}
{{ row.key.name }} {% if row.key.is_active %}Active{% else %}Revoked{% endif %}
{% comment %} The prefix, never the key. Nothing can render the value again — it is not stored (CONTRIBUTING → Secrets), only a keyed digest. {% endcomment %}
{{ row.workspace.name }} · {{ row.key.display_handle }} · {{ row.scopes }} · {% if row.key.is_active %}last used {{ row.key.last_used_at|default:"never" }}{% else %}revoked {{ row.key.revoked_at }}{% endif %}
{% if row.key.is_active %} {% endif %}
{% endfor %}
{% else %}

No keys yet

Let Zapier, scripts, or your own backend access this workspace.

{% endif %}
{% endblock %} {% block alpine_components %}{{ block.super }}{% include "partials/_list_behaviours.html" %}{% endblock %}