Menu
Enterprise

Admin API documentation

Grafana Enterprise Traces (GET) provides an administrative HTTP API for managing cluster resources, such as tenants and tokens. The GET Admin API has three versions. The third version (/admin/api/v3) is currently supported.

”cautions”

Admin API version v1 /admin/api/v1/ and v2 /admin/api/v2/ endpoints are deprecated and will be removed in a future release of GET.

API operations

The API supports standard CRUD (create, read, update, and delete) operations for most resources.

  • Creates are issued via POST requests
  • Reads via GET requests
  • Updates via PUT requests
  • Deletes via DELETE requests

When running multiple instances of the Admin API, you should enable leader election so that all mutations occur on a single, leader-elected instance.

Write consistency (If-Match and ETag headers)

To ensure concurrent changes are propagated in a way that avoids unintentional overwrites, an If-Match header is required for all requests that mutate data. The current version of a resource to be sent in the If-Match header can be found in the ETag header returned on all GET and PUT requests that return a single resource in the response body.

Here are a few examples of how to get the value of the ETag header using curl. The first example uses the argument -D - to write all headers to standard out, and then parses for the ETag header.

console
curl -u :$API_TOKEN -sD - -o /dev/null http://localhost:3100/admin/api/v3/accesspolicies/{name} | grep -i ETag | cut -d " " -f 2

This second example uses the -v option in curl to print the headers along with the response payload.

console
curl -u :$API_TOKEN -v http://localhost:3100/admin/api/v3/accesspolicies/{name}

When making a request to mutate data, make sure to include the double quotes (") around the value in the If-Match header. For example, the following is a request to update the access policy named the-access-policy, currently at version 1:

console
curl -u :$API_TOKEN -X PUT -H 'If-Match: "1"' http://localhost:3100/admin/api/v3/accesspolicies/the-access-policy --data '{"status": "active", "realms": [{"tenant": "traces-enterprise-dev", "cluster": "traces-enterprise-dev"}], "scopes": ["traces:write"]}'

Optionally, a wildcard "*" may be passed as the If-Match version which effectively disables the write consistency protections and allows any current version to be updated.

Cluster API

List clusters

GET /admin/api/v3/clusters

Response:

json
{
  "items": [
    {
      "name":  "<string>",              // cluster name
      "display_name": "<string>",       // cluster display name
      "created_at": "<rfc3339 string>", // date created
      "kind": "<string>",               // cluster type
      "base_url": "<string>"            // Base URL of the cluster, optional
    }
    ...
  ],
  "type": "cluster"
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/clusters | jq
{
  "items": [
    {
      "name": "traces-enterprise-dev",
      "display_name": "traces-enterprise-dev",
      "created_at": "2020-07-13T16:50:41.953793Z",
      "kind": "traces",
      "base_url": ""
    }
  ],
  "type": "cluster"
}

Get cluster

GET /admin/api/v3/clusters/{name}

NOTES:

  • There is no ETag header on a cluster response because clusters are immutable.

Response:

json
{
  "name":  "<string>",              // cluster name
  "display_name": "<string>",       // cluster display name
  "created_at": "<rfc3339 string>", // date created
  "kind": "<string>",               // cluster type
  "base_url": "<string>"            // Base URL of the cluster, optional
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/clusters/traces-enterprise-dev | jq
{
  "name": "traces-enterprise-dev",
  "display_name": "traces-enterprise-dev",
  "created_at": "2020-07-13T16:50:41.953793Z",
  "kind": "traces",
  "base_url": ""
}

Tenant API

Model

The tenant model is made up of the following fields:

  • name: The machine-readable name of a tenant. It must be between 3 and 64 characters and only include the following characters, [a-z0-9-_]. Once set, this field is immutable.
  • display_name: The human-readable name of a tenant. It can contain any set of characters and can be changed.
  • status: The current status of this tenant. It can have the following values:
    • active
    • inactive
    • unknown
  • cluster: The name of the Grafana Enterprise Traces cluster that this tenant is scoped to. You will only be able to write/query this tenant from this cluster.
  • limits: Currently unsupported and does not affect the usage of the tenant.

List tenants

GET /admin/api/v3/tenants

NOTES:

  • This endpoint only returns tenants in an active status. To get all tenants including inactive ones use the query parameter include-non-active=true

Response:

json
{
  "items": [
    {
      "name": "<string>",
      "display_name": "<string>",
      "created_at": "<rfc3339 string>",
      "status": "<string>",
      "cluster": "<string>",
      "limits": {
        ...
      }
    },
    ...
  ],
  "type": "tenant"
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/tenants | jq
{
  "items": [
	{
  	"name": "traces-enterprise-dev",
  	"display_name": "Grafana Enterprise Traces dev tenant",
  	"created_at": "2023-10-24T18:43:55.150775951Z",
  	"status": "active",
  	"cluster": "traces-enterprise-dev"
	}
  ],
  "type": "tenant"
}

Create tenant

POST /admin/api/v3/tenants

Because tenant names are unique, you can’t create a new tenant with the same name as a tenant that already exists but is in the inactive state. Instead, to reuse the inactive tenant name, re-enable the inactive tenant by updating its state to active. To make this change, use the Update Tenant endpoint.

When creating a tenant via this API call, you don’t have to specify the status field, because the status is always overwritten by the API to be active.

Response:

console
{
  "name": "<string>",
  "display_name": "<string>",
  "created_at": "<rfc3339 string>",
  "status": "<string>",
  "cluster": "<string>"
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/tenants \
--data '{"name": "traces-enterprise-dev", "status": "active", "display_name": "Grafana Enterprise Traces dev tenant", "cluster": "traces-enterprise-dev"}'
{
  "name": "traces-enterprise-dev",
  "display_name": "Grafana Enterprise Traces dev tenant",
  "created_at": "2023-10-24T18:43:55.150775951Z",
  "status": "active",
  "cluster": "traces-enterprise-dev"
}

Update tenant

PUT /admin/api/v3/tenants/{name}

NOTES:

  • The name field of the object in the request body is ignored during updates.
  • The created_at field may not be modified during updates.
  • If-Match header matching the current version is required.

Response:

json
{
  "name": "<string>",
  "display_name": "<string>",
  "created_at": "<rfc3339 string>",
  "status": "<string>",
  "cluster": "<string>",
  "limits": {
    ...
  }
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/tenants/traces-enterprise-dev \
-X PUT -H 'If-Match: "1"' \
--data '{"display_name": "Grafana Enterprise Traces dev tenant UPDATE", "status": "active", "cluster": "traces-enterprise-dev"}' | jq
{
  "name": "traces-enterprise-dev",
  "display_name": "Grafana Enterprise Traces dev tenant UPDATE",
  "created_at": "2023-10-24T18:43:55.150775951Z",
  "status": "active",
  "cluster": "traces-enterprise-dev"
}

Get tenant

GET /admin/api/v3/tenants/{name}

NOTES:

  • The current version of the tenant will be returned in an ETag header on the response.

Response:

json
{
  "name": "<string>",
  "display_name": "<string>",
  "created_at": "<rfc3339 string>",
  "status": "<string>",
  "cluster": "<string>",
  "limits": {
    ...
  }
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/tenants/traces-enterprise-dev | jq
{
  "name": "traces-enterprise-dev",
  "display_name": "Grafana Enterprise Traces dev tenant UPDATE",
  "created_at": "2023-10-24T18:43:55.150775951Z",
  "status": "active",
  "cluster": "traces-enterprise-dev"
}

Delete tenant

In Admin API version v3, delete operations are no longer supported and are replaced by soft deletes. Use the endpoint PUT /admin/api/v3/tenants/{name} with "status": "inactive" instead. This operation will inactivate a tenant and subsequent HTTP requests for the tenant will fail with a 401 Unauthorized HTTP status code.

To re-enable a tenant, use the endpoint PUT /admin/api/v3/tenants/{name} with "status": "active".

PUT /admin/api/v3/tenants/{name}

json
{
  "status": "inactive",
  "cluster": "<string>"
}

NOTES:

  • If-Match header matching the current version is required.

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/tenants/traces-enterprise-dev \
-X PUT -H 'If-Match: "2"' \
--data '{"status": "inactive", "cluster": "traces-enterprise-dev"}' | jq
{
  "name": "traces-enterprise-dev",
  "created_at": "2023-10-24T18:43:55.150775951Z",
  "status": "inactive",
  "cluster": "traces-enterprise-dev"
}

Access policy API

Model

The access policy model is made up of the following fields:

  • name: The machine-readable name of an access policy. It must be between 3 and 64 characters and only include the following characters, [a-z0-9-_]. Once set, this field is immutable.
  • display_name: The human-readable name of the access policy. It can contain any set of characters and can be changed.
  • status: The current status of the access policy. It can have the following values:
    • active
    • inactive
    • unknown
  • realms: The name of the realms which designate the tenant/cluster pairs for the access policy.

Realms

Realms designate the tenant/cluster pairs that the access policy allows requests for:

  • tenant: This field must be set to an existing tenant or *. * denotes access to all tenants.
  • cluster: This field must be set to an existing cluster.

Scopes

Scopes designate what operations tokens assigned to this access policy will be able to do when calling the GET API.

  • traces:read: Permission to view data from a tenant
  • traces:write: Permission to write data to a tenant
  • admin: Permission to perform admin operations

List access policies

GET /admin/api/v3/accesspolicies

NOTES:

  • This endpoint only returns access policies in an active status. To get all access policies including inactive ones, use the query parameter include-non-active=true

Response:

json
{
  "items": [
    {
      "name": "<string>",
      "display_name": "<string>",
      "created_at": "<rfc3339 string>",
      "status": "<string>",
      "realms": [
        {
          "tenant": "<string>",
          "cluster": "<string>"
        }
      ],
      "scopes": [
        "<string>",
        ...
      ]
    },
    ...
  ],
  "type": "access_policy"
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/accesspolicies | jq
{
  "items": [
	{
  	  "name": "__system__",
  	  "display_name": "System",
  	  "created_at": "1970-01-01T00:00:00Z",
  	  "status": "active",
  	  "realms": [
    	    {
           "tenant": "__system__",
           "cluster": "traces-enterprise-dev"
    	    }
  	  ],
  	  "scopes": [
    	    "metrics:read",
    	    "rules:read"
  	  ]
	},
	{
  	  "name": "__admin__",
  	  "display_name": "Admin",
  	  "created_at": "1970-01-01T00:00:00Z",
  	  "status": "active",
  	  "realms": null,
  	  "scopes": [
    	    "admin"
  	  ]
	}
  ],
  "type": "access_policy"
}

Create access policy

POST /admin/api/v3/accesspolicies

Payload:

json
{
  "name": "<string>",
  "display_name": "<string>",
  "created_at": "<rfc3339 string>",
  "realms": [
    {
      "tenant": "<string>",
      "cluster": "<string>"
    }
  ],
  "scopes": [
    "<string>",
    ...
  ]
}

Because access policy names are unique, you cannot create a new access policy with the same name as an access policy that already exists but is in the inactive state.

To reuse the inactive access policy name, re-activate the inactive access policy by updating its state to active. To make this change, use the Update Access Policy endpoint.

When creating an access policy via this API call, it isn’t required to specify the status field, because the status is always overwritten by the API to be active.

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/accesspolicies \
--data '{"name": "primary-policy", "display_name": "Primary access policy", "realms": [{ "tenant": "primary-tenant", "cluster": "traces-enterprise-dev" }], "scopes": [ "traces:write", "traces:read" ]}' | jq
{
  "name": "primary-policy",
  "display_name": "Primary access policy",
  "created_at": "2023-10-24T19:20:24.098774824Z",
  "status": "active",
  "realms": [
	{
  	  "tenant": "primary-tenant",
  	  "cluster": "traces-enterprise-dev"
	}
  ],
  "scopes": [
	"traces:write",
	"traces:read"
  ]
}

Update access policy

PUT /admin/api/v3/accesspolicies/{name}

NOTES:

  • If-Match header matching the current version is required.
  • Update differs from create in that only the Display Name, Realms, and Scopes can be updated.

Payload:

json
{
  "display_name": "<string>",
  "status": "<string>",
  "realms": [
    {
      "tenant": "<string>",
      "cluster": "<string>"
    }
  ],
  "scopes": [
    "<string>",
    ...
  ]
}

Example:

console
$ curl -v -u :$API_TOKEN http://localhost:3100/admin/api/v3/accesspolicies/primary-policy -X PUT -H 'If-Match: "1"' \
--data '{"name": "primary-policy", "display_name": "Primary access policy UPDATE", "status": "active", "realms": [{ "tenant": "primary-tenant", "cluster": "traces-enterprise-dev" }], "scopes": [ "traces:write", "traces:read" ]}' | jq
{
  "name": "primary-policy",
  "display_name": "Primary access policy UPDATE",
  "created_at": "2023-10-24T19:20:24.098774824Z",
  "status": "active",
  "realms": [
	{
  	  "tenant": "primary-tenant",
  	  "cluster": "traces-enterprise-dev"
	}
  ],
  "scopes": [
	"traces:write",
	"traces:read"
  ]
}

Get access policy

GET /admin/api/v3/accesspolicies/{name}

NOTES:

  • The current version of the access policy is returned in an ETag header on the response.

Response:

json
{
  "name": "<string>",
  "display_name": "<string>",
  "created_at": "<rfc3339 string>",
  "status": "<string>",
  "realms": [
    {
      "tenant": "<string>",
      "cluster": "<string>"
    }
  ],
  "scopes": [
    "<string>",
    ...
  ]
}

Example:

console
$ curl -v -u :$API_TOKEN http://localhost:3100/admin/api/v3/accesspolicies/primary-policy | jq
{
  "name": "primary-policy",
  "display_name": "Primary access policy UPDATE",
  "created_at": "2023-10-24T19:20:24.098774824Z",
  "status": "active",
  "realms": [
	{
  	  "tenant": "primary-tenant",
  	  "cluster": "traces-enterprise-dev"
	}
  ],
  "scopes": [
	"traces:write",
	"traces:read"
  ]
}

Delete access policy

In Admin API version v3, delete operations are no longer supported and have been replaced by soft deletes. Use the endpoint PUT /admin/api/v3/accesspolicies/{name} with "status": "inactive" instead. This operation will inactivate an access policy and subsequent HTTP requests with an associated token will fail with a 401 Unauthorized HTTP status code.

To re-enable an access policy, use the endpoint PUT /admin/api/v3/accesspolicies/{name} with "status": "active".

PUT /admin/api/v3/accesspolicies/{name}

NOTES:

  • If-Match header matching the current version is required.

Example:

console
$ curl -v -u :$API_TOKEN http://localhost:3100/admin/api/v3/accesspolicies/primary-policy -X PUT -H 'If-Match: "2"' \
--data '{"status": "inactive", "realms": [{ "tenant": "primary-tenant", "cluster": "traces-enterprise-dev" }], "scopes": [ "traces:write", "traces:read" ]}' | jq .
{
  "name": "primary-policy",
  "created_at": "2023-10-24T19:20:24.098774824Z",
  "status": "inactive",
  "realms": [
	{
  	  "tenant": "primary-tenant",
  	  "cluster": "traces-enterprise-dev"
	}
  ],
  "scopes": [
	"traces:write",
	"traces:read"
  ]
}

Token API

List tokens

GET /admin/api/v3/tokens

NOTES:

  • This endpoint only returns tokens in an active status. To get all tokens including inactive ones, use the query parameter include-non-active=true

Response:

json
{
  "items": [
    {
      "name": "<string>",
      "display_name": "<string>",
      "created_by": "<string>",
      "created_at": "<rfc3339 string>",
      "status": "<string>",
      "access_policy": "<string>",
      "expiration": "<rfc3339 string>"
    },
    ...
  ],
  "type": "token"
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/tokens | jq

Create token

POST /admin/api/v3/tokens

Payload:

json
{
  "name": "<string>",
  "display_name": "<string>",
  "created_at": "<rfc3339 string>",
  "access_policy": "<string>",
  "expiration": "<rfc3339 string>"
}

Because token names are unique, you can’t create a new token with the same name as a token that already exists but is in the inactive state. Instead, to reuse the inactive token name, re-enable the inactive token by updating its state to active. To make this change, use the PUT /admin/api/v3/tokens/{name} endpoint.

When creating a token via this API call, it isn’t required to specify the status field, because the status is always overwritten by the API to be active.

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/tokens \
--data '{ "name": "primarytoken", "display_name": "Primary token", "access_policy": "primary-policy" }' | jq .
{
  "name": "primarytoken",
  "display_name": "Primary token",
  "created_at": "2023-10-24T19:31:49.183102304Z",
  "status": "active",
  "access_policy": "primary-policy",
  "expiration": "0001-01-01T00:00:00Z",
  "token": "<token>"
}

Get token

GET /admin/api/v3/tokens/{name}

NOTES:

  • The current version of the token is returned in an ETag header on the response.

Response:

json
{
  "name": "<string>",
  "display_name": "<string>",
  "created_at": "<rfc3339 string>",
  "status": "<string>",
  "access_policy": "<string>",
  "expiration": "<rfc3339 string>"
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/tokens/primarytoken | jq
{
  "name": "primarytoken",
  "display_name": "Primary token",
  "created_at": "2023-10-24T19:31:49.183102304Z",
  "status": "active",
  "access_policy": "primary-policy",
  "expiration": "0001-01-01T00:00:00Z"
}

Delete token

In Admin API version v3, delete operations are no longer supported and have been replaced by soft deletes. Use the endpoint PUT /admin/api/v3/tokens/{name} with "status": "inactive" instead. This operation inactivates a token and subsequent HTTP requests with the token fails with a 401 Unauthorized HTTP status code.

To re-enable a token, use the endpoint PUT /admin/api/v3/tokens/{name} with "status": "active".

PUT /admin/api/v3/tokens/{name}

json
{
  "status": "inactive"
}

NOTES:

  • If-Match header matching the current version is required.

Response:

console
{
  "name": "<string>",
  "display_name": "<string>",
  "created_at": "<rfc3339 string>",
  "status": "<string>",
  "access_policy": "<string>",
  "expiration": "<rfc3339 string>"
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/tokens/primarytoken \
-X PUT -H 'If-Match: "1"' \
--data '{"status": "inactive"}' | jq
{
  "name": "primarytoken",
  "display_name": "Primary token",
  "created_at": "2023-10-24T19:31:49.183102304Z",
  "status": "inactive",
  "access_policy": "primary-policy",
  "expiration": "0001-01-01T00:00:00Z"
}

License API

List licenses

GET /admin/api/v3/licenses

Response:

json
{
  "items": [
    {
      "name": "<string>",
      "display_name": "<string>",
      "created_by": "<string>",
      "created_at": "<rfc3339 string>",
      "token": {
        "jti": "<string>",
        "iss": "<string>",
        "sub": "<string>",
        "iat": "<int64>",
        "exp": "<int64>",
        "nbf": "<int64>",
        "lexp": "<int64>",
        "lid": "<string>",
        "max_users": "<int64>",
        "included_admins": "<int64>",
        "included_viewers": "<int64>",
        "lic_exp_warn_days": "<int64>",
        "prod": [
          "<string>",
          ...
        ],
        "company": "<string>",
        "slug": "<string>",
      }
    },
    ...
  ],
  "type": "license"
}

Example:

console
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/licenses | jq
{
  "items": [
	{
  	"name": "123456",
  	"display_name": "Organisation, Inc.",
  	"created_by": "bootstrap",
  	"created_at": "2023-10-24T18:33:51.162552844Z",
  	"token": {
     	  "jti": "5999456",
    	  "iss": "https://grafana.com",
    	  "sub": "get-heds",
    	  "iat": 1692468937,
    	  "exp": 1723224174,
    	  "nbf": 1691601474,
    	  "lexp": 1723224174,
    	  "lid": "530868",
    	  "max_users": 0,
    	  "included_admins": -1,
    	  "included_viewers": -1,
    	  "lic_exp_warn_days": 30,
    	  "prod": [
      	"grafana-enterprise-traces"
    	  ],
    	  "company": "Organisation, Inc.",
    	  "slug": "organisationinc"
    	  }
	}
  ],
  "type": "license"
}

Feature detection API

Get product and feature information

GET /admin/api/v3/features

Response:

json
{
  "name": "<string>",
  "version": "<string>",
  "features": {
      "<string>": "<string>",
      ...
  }
}

Example:

json
$ curl -u :$API_TOKEN http://localhost:3100/admin/api/v3/features | jq
{
  "name": "GET",
  "version": "v2.2.3",
  "features": {
	"editable_access_policies": "v1",
	"editable_tenants": "v1"
  }
}