An account owns tags and API keys. The account that owns your key is your master account; accounts you create through the API are subaccounts of it — the unit of multi-tenancy. Creating a subaccount also mints its first API key.
When to use subaccounts
Subaccounts are optional, and for most integrations the answer is no — you can do everything with your master account’s key. Reach for one only when you have a concrete separation requirement.
What a subaccount isolates is tags and the keys that read them: a key sees only
its own account’s tags, and a tag lookup or verification across accounts returns
404. It’s tag and credential scoping — not a billing or quota boundary.
Common reasons to create one:
- Per-customer isolation (multi-tenant / reseller). You serve multiple independent customers whose tags must stay walled off from each other — one subaccount per customer, each with its own key.
- Business-unit or regional separation. One organization that needs hard separation between legal entities or regions.
- Environment separation. A dedicated subaccount for test/staging tags so they never mix with production — useful even for a single-customer integration.
Skip them if you can’t point to two parties — or environments — that must not see each other’s tags. A single application with one set of tags should just use the master account directly; a subaccount would only add key management for no benefit.
Decide before you provision at scale. A tag is owned permanently by the account that created it, and there’s no endpoint to move it to another account later. So if a tenant or environment will ever need its own isolated tags, create its subaccount first and provision under that subaccount’s key — you can’t retrofit the split onto tags that already exist.
Fields
| Field | Type | Notes |
|---|---|---|
id |
string | acc_-prefixed, assigned by the platform. |
name |
string | Required. 1–100 characters. |
A subaccount is always created beneath the account whose key you present; you don’t pass a parent — it’s inferred from the key.
Create a subaccount
POST /api/v1/accounts
Request
{
"data": {
"type": "accounts",
"attributes": {
"name": "Metropolitan Museum — Night Watch"
}
}
}
name is the only required attribute. The request also accepts optional profile
attributes if you want to store them on the account: company, vat,
country, address, city, state, zip_code.
curl https://platform.tagbase.io/api/v1/accounts \
-X POST \
-H "Authorization: Bearer $TAGBASE_API_KEY" \
-H "Content-Type: application/vnd.api+json" \
-d '{ "data": { "type": "accounts", "attributes": { "name": "Metropolitan Museum — Night Watch" } } }'
const res = await fetch("https://platform.tagbase.io/api/v1/accounts", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TAGBASE_API_KEY}`,
"Content-Type": "application/vnd.api+json",
},
body: JSON.stringify({
data: { type: "accounts", attributes: { name: "Metropolitan Museum — Night Watch" } },
}),
});
const account = await res.json();
$response = $client->post("https://platform.tagbase.io/api/v1/accounts", [
"headers" => [
"Authorization" => "Bearer " . getenv("TAGBASE_API_KEY"),
"Content-Type" => "application/vnd.api+json",
],
"json" => [
"data" => ["type" => "accounts", "attributes" => ["name" => "Metropolitan Museum — Night Watch"]],
],
]);
$account = json_decode((string) $response->getBody(), true);
account =
Req.post!("https://platform.tagbase.io/api/v1/accounts",
headers: [
{"authorization", "Bearer #{System.fetch_env!("TAGBASE_API_KEY")}"},
{"content-type", "application/vnd.api+json"}
],
json: %{data: %{type: "accounts", attributes: %{name: "Metropolitan Museum — Night Watch"}}}
).body
Response — 201 Created
The new subaccount, plus its freshly minted API key as an included
api_keys resource. The key’s secret is shown here and
nowhere else — capture it now.
{
"data": {
"type": "accounts",
"id": "acc_abcdef0123456789",
"attributes": { "name": "Metropolitan Museum — Night Watch" },
"relationships": {
"api_keys": {
"data": [ { "type": "api_keys", "id": "key_abcdef0123456789" } ]
}
}
},
"included": [
{
"type": "api_keys",
"id": "key_abcdef0123456789",
"attributes": { "secret": "key_abcdef0123456789:superstrongrandomsecret" }
}
]
}
Store included[].attributes.secret immediately — it’s the credential you’ll use
for every request made on behalf of this subaccount.
Errors
| Status | When |
|---|---|
400 |
The body has no data.attributes object. |
401 |
Missing, invalid, or revoked key. |
422 |
Validation failed — e.g. name is missing or out of length. |
Notes
- There is no endpoint to read, list, or update an account after creation. Record
the returned
idand key when you create it. - Subaccounts nest one level beneath the presenting account; deeper hierarchies aren’t exposed through the API.