Skip to main content

Consuming variables

Everything here rests on one call:

GET /variablevalues?set={id}&tag={Group/Tag}

which returns a flat name-to-string map — deliberately, so it can be poured straight into environment variables or a settings file without anything having to walk a structure first.

Setting up the consumer's account​

A consumer should hold as little as possible. For a deployment that only reads:

PermissionWhy
VariableReadRequired by /variablevalues
VariableReadSecretsOnly if the deployment needs actual secrets rather than hints

VariableList is not needed — the consumer knows which sets it wants.

  1. Create a group holding exactly those.
  2. Create an account for the consumer and put it in that group.
  3. Sign in as that account and create an API key for it.
tip

VariableReadSecrets is what separates a deployment that can read secrets from one that cannot. If your pipeline injects secrets from a different vault and only wants non-sensitive config from TagShape, leave it off — the sensitive entries will come back as hints, which are harmless.

In a shell script​

#!/usr/bin/env bash
set -euo pipefail

JWT=$(curl -sS -D - -o /dev/null -X POST "$IDENTITY_API/apikeyjwt" \
-H "x-tagshape-api: $TAGSHAPE_API_KEY" \
| awk 'BEGIN{IGNORECASE=1} /^x-tagshape-auth:/ {print $2}' | tr -d '\r')

[ -n "$JWT" ] || { echo "Could not exchange the API key for a token" >&2; exit 1; }

curl -sS --get "$LIBRARY_API/variablevalues" \
--data-urlencode "set=1" \
--data-urlencode "tag=Environment/$ENVIRONMENT" \
--data-urlencode "tag=Region/$REGION" \
-H "x-tagshape-auth: $JWT" \
> config.json

Turn it into environment variables:

while IFS=$'\t' read -r name value; do
export "$name=$value"
done < <(jq -r '.items | to_entries[] | [.key, .value] | @tsv' config.json)

Exchange the key once per run, not per request — the JWT is good for its full duration (60 minutes by default).

In PowerShell​

$response = Invoke-WebRequest -Method Post -Uri "$env:IDENTITY_API/apikeyjwt" `
-Headers @{ 'x-tagshape-api' = $env:TAGSHAPE_API_KEY }
$jwt = $response.Headers['x-tagshape-auth']

$query = "set=1&tag=Environment/$env:ENVIRONMENT&tag=Region/$env:REGION"
$config = Invoke-RestMethod -Uri "$env:LIBRARY_API/variablevalues?$query" `
-Headers @{ 'x-tagshape-auth' = $jwt }

foreach ($entry in $config.items.PSObject.Properties) {
[Environment]::SetEnvironmentVariable($entry.Name, $entry.Value)
}

In a .NET service​

public sealed class TagShapeConfigurationProvider(HttpClient client, string[] tags, int[] sets)
{
public async Task<Dictionary<string, string>> LoadAsync(CancellationToken cancellationToken)
{
var query = string.Join("&",
sets.Select(set => $"set={set}")
.Concat(tags.Select(tag => $"tag={Uri.EscapeDataString(tag)}")));

var response = await client.GetFromJsonAsync<ListDataSetDictionary<string, string>>(
$"/variablevalues?{query}", cancellationToken);

return response?.Items ?? [];
}
}

The JWT belongs on the HttpClient's default headers as x-tagshape-auth, refreshed before it expires.

Several library sets​

GET /variablevalues?set=1&set=2&tag=Environment/Production

Sets are walked in name order, not query-string order, and a variable present in two sets takes its value from the set that sorts later. If you rely on one overriding another, name them so the ordering is obvious — renaming a set can change which one wins.

Choosing tags at deploy time​

Tags describe where you are, so they usually come from the same place the deployment target does:

# CI variables
TAGSHAPE_TAGS: "Environment/Production,Region/EU,Tier/Enterprise"
TAG_ARGS=()
IFS=',' read -ra TAGS <<< "$TAGSHAPE_TAGS"
for tag in "${TAGS[@]}"; do TAG_ARGS+=(--data-urlencode "tag=$tag"); done

curl -sS --get "$LIBRARY_API/variablevalues" --data-urlencode "set=1" "${TAG_ARGS[@]}" \
-H "x-tagshape-auth: $JWT"

Asking for a tag that does not exist is not an error — it simply matches nothing, and values fall back. That makes typos quiet, so validate the tag list against GET /tags in CI if it is assembled by hand.

Diagnosing an unexpected value​

Use the preview endpoint. It runs identical resolution and returns the whole winning value with its tags:

curl -sS --get "$LIBRARY_API/variablevalues/preview" \
--data-urlencode "set=1" \
--data-urlencode "tag=Environment/Production" \
-H "x-tagshape-auth: $JWT" | jq '.items.DatabaseConnection'

The tags on the winner tell you immediately whether the problem is a mistagged value or a tag you forgot to ask for. The usual cause is the fourth rule of resolution: a value carrying a tag you did not ask for cannot win.

Credits​

Each GET /variablevalues call costs 10 credits — one charge per call, however many sets, tags or values are involved — so fetching everything in a single call is the cheapest way to consume it. The preview endpoint costs the same, so keep it for diagnosis rather than for a pipeline.

Failure modes​

SymptomCause
400 Bad RequestNo set parameter. At least one is required.
429 Too Many RequestsThe organization has run out of credits. The body reads Insufficient credits: N available, C required. Used credits reset when the next subscription payment is applied.
404 Not FoundA set names a library set that does not exist, or belongs to another organization. The whole request fails, not just that set.
403 ForbiddenThe account lacks VariableRead.
Secrets come back as hintsThe account lacks VariableReadSecrets.
A variable is missing from the responseIt has no untagged default and nothing matched. Add a default value.
The wrong valueUse /variablevalues/preview and check the winner's tags.