Tags
A tag is a label you apply to posts and ideas so you can group and filter them. Tags belong to the organization and are shared by everyone in it, rather than to a single channel or person.
The whole tag API is an early preview. It can change, or be withdrawn, without a deprecation period — see API Standards for what that means in practice.
Reading tags
query {
tagsV2(first: 20, input: { organizationId: "your_org_id" }) {
edges {
node {
id
name
color
colorName
isLocked
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Tags come back a page at a time, sorted by name in ascending order. Pass the previous page's pageInfo.endCursor as after to walk the pages — see Pagination. Asking for more than 100 in one call is rejected.
When you already have the ID, tag(input: { id: ... }) fetches one directly. It resolves to null with a NOT_FOUND entry in the errors array when no tag has that ID.
Reading tags needs the posts:read scope.
Colors
Two fields describe the same color.
color is a literal hex triplet such as #F523F1 — # followed by exactly six hex digits. Shorthand such as #F51 is rejected.
colorName is a stable identifier for a Buffer palette color, and is null when the tag uses a custom one. Prefer it when you want to render Buffer's own colors rather than reproduce a hex value. It is read-only: there is no way to ask for a palette color by name on write, so send the hex value and read colorName back to find out whether it landed on one.
Locked tags
A tag can be locked, which happens when an organization holds more tags than its plan allows, usually after a downgrade. Buffer locks the excess rather than deleting it, so nothing is lost if the plan is upgraded again.
A locked tag can still be read, deleted, and applied to posts. It just cannot be renamed or recolored.
Creating, editing and deleting tags
Creating, editing and deleting tags need the posts:write scope, so a read-only token can list an organization's tags but cannot change them.
mutation {
createTag(input: {
organizationId: "your_org_id",
tag: { name: "Summer sales", color: "#F523F1" }
}) {
... on TagActionSuccess {
tag { id name color colorName isLocked }
}
... on MutationError {
message
}
}
}
updateTag takes the tag's ID and replaces both its name and its color, so send the current value for whichever one you are not changing. It does not take an organizationId — the organization comes from the tag. It refuses to edit a locked tag.
deleteTag removes the tag from every post, idea and content item carrying it; those items are otherwise untouched, and the deletion cannot be undone. A locked tag can be deleted, and deleting an unlocked one frees a slot, so the organization's oldest locked tag is unlocked in its place.
What can go wrong
Select ... on MutationError { message } on every tag mutation. Every error the three mutations can return implements that interface, so the catch-all keeps working as the API changes — see Error Handling.
Three failures are worth branching on, because the caller can act on each:
| Error | When | What to do |
|---|---|---|
DuplicateError |
Another tag in the organization already has that name. Names are compared exactly, so Summer sales and summer sales can both exist. |
Pick a different name. |
LimitReachedError |
createTag only. The organization is at its plan's tag limit — 3 on the Free plan, 250 on a paid one. |
Delete a tag, or upgrade the plan. |
InvalidInputError |
The name or the color is malformed — an empty name, a name over 100 characters, a color that is not a six-digit hex triplet. | Correct the input. |
Editing a locked tag is currently refused with UnauthorizedError. That reads as a permissions problem, but it is not one — an organization administrator gets the same refusal, because the tag is in a plan-limited state rather than a protected one. Treat it as "this tag cannot be edited right now", not as "this caller lacks access", and expect the error type to change.
NotFoundError, UnauthorizedError, UnexpectedError and RestProxyError are also members of the three tag payload unions today, and all four are on their way out — they will be reported in the response's top-level errors array instead. Do not write new code that names them. The ... on MutationError { message } selection above survives their removal; an inline fragment naming one of them does not.
Tags on posts
A post carries its tags as tagIds. See Content Items for grouping content across channels, where the tags apply to the item as a whole.