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:
| Permission | Why |
|---|---|
VariableRead | Required by /variablevalues |
VariableReadSecrets | Only if the deployment needs actual secrets rather than hints |
VariableList is not needed — the consumer knows which sets it wants.
- Create a group holding exactly those.
- Create an account for the consumer and put it in that group.
- Sign in as that account and create an API key for it.
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.
Failure modes
| Symptom | Cause |
|---|---|
400 Bad Request | No set parameter. At least one is required. |
404 Not Found | A set names a library set that does not exist, or belongs to another organization. The whole request fails, not just that set. |
403 Forbidden | The account lacks VariableRead. |
| Secrets come back as hints | The account lacks VariableReadSecrets. |
| A variable is missing from the response | It has no untagged default and nothing matched. Add a default value. |
| The wrong value | Use /variablevalues/preview and check the winner's tags. |