Start small
Begin with the fields you need today. Schema versioning lets you add fields later without breaking existing data.
Tags in Thogits are more than labels — they carry structured field schemas that define what data a thogit stores. Good schema design makes filtering powerful, keeps data consistent, and lets your system evolve without breaking existing thogits.
Start small
Begin with the fields you need today. Schema versioning lets you add fields later without breaking existing data.
One tag per concern
Separate concerns into distinct tags. Use “Task” for workflow, “Priority” for priority, “Assignment” for ownership — not one mega-tag.
Name consistently
Use PascalCase for tag names (ProjectTask, SprintGoal) and snake_case for field names (due_date, story_points).
Use References for relationships
Link thogits together with Reference fields instead of duplicating data. This enables reference traversal in filters.
| Type | Use for | Example |
|---|---|---|
String | Free-form text | description, notes |
Number | Quantities, priorities, scores | priority, story_points |
Boolean | Binary flags | is_billable, requires_review |
Date | Points in time | due_date, started_at |
Select | Workflow states, enums (single choice) | status, severity |
MultiSelect | Labels, categories (multiple choice) | labels, skills |
Reference | Links to other thogits | assignee, project, parent |
Select fields are ordered — the position of each variant matters. This enables ordinal filters like select_gte (at least this far in the workflow) and select_lte.
{ "status": { "type": "Select", "variants": [ "Backlog", "Todo", "In Progress", "In Review", "Done" ] }}With this ordering, {"Task.status": {"select_gte": "In Progress"}} matches thogits that are “In Progress”, “In Review”, or “Done” — anything at that stage or later.
Variants can carry additional fields that only apply when that variant is active. This is useful for conditional data — a “Blocked” status needs a reason, a “Deferred” status needs a target date.
{ "status": { "type": "Select", "variants": [ "Todo", "In Progress", {"name": "Blocked", "fields": {"reason": "String"}}, {"name": "Deferred", "fields": {"until": "Date"}}, "Done" ] }}When setting field values, variant sub-fields are stored flat alongside other fields:
{ "status": {"variant": "Blocked"}, "reason": "Waiting on design review"}Use MultiSelect when a thogit can belong to multiple categories simultaneously. Unlike Select, MultiSelect has no ordering semantics.
{ "labels": { "type": "MultiSelect", "variants": ["Bug", "Feature", "Frontend", "Backend", "P1", "P2", "P3"] }}Set values as an array:
{ "labels": ["Bug", "Frontend", "P1"]}Reference fields store a ULID pointing to another thogit. This creates a typed link that you can traverse in filters using the -> operator.
{ "assignee": "Reference", "project": "Reference"}Set values by providing the target thogit’s ID:
{ "assignee": "01JQXYZ000PERSON00000ALICE", "project": "01JQXYZ000PROJECT0000API"}When you update a tag’s fields (add, rename, or remove fields), the schema_version increments automatically. Existing thogits keep their old version and field values until explicitly updated.
This means:
Use the get_outdated_thogit_tags MCP tool (or check schema_version on thogit tags) to find thogits that are behind the current schema version.
Here is a full schema design for a project management system with four interconnected tags.
curl -X POST https://app.thogits.com/api/tags \ -H "Content-Type: application/json" \ -b cookies.txt -c cookies.txt \ -d '{ "name": "Person", "fields": { "department": { "type": "Select", "variants": [ "Engineering", "Design", "Product", "Marketing" ] }, "role": "String" } }'The lead field is a Reference to a Person thogit.
curl -X POST https://app.thogits.com/api/tags \ -H "Content-Type: application/json" \ -b cookies.txt -c cookies.txt \ -d '{ "name": "Project", "fields": { "name": "String", "lead": "Reference", "status": { "type": "Select", "variants": [ "Planning", "Active", "Paused", "Complete" ] }, "start_date": "Date", "target_date": "Date" } }'curl -X POST https://app.thogits.com/api/tags \ -H "Content-Type: application/json" \ -b cookies.txt -c cookies.txt \ -d '{ "name": "Sprint", "fields": { "project": "Reference", "number": "Number", "start_date": "Date", "end_date": "Date", "goal": "String" } }'References assignee (Person), project (Project), and sprint (Sprint).
curl -X POST https://app.thogits.com/api/tags \ -H "Content-Type: application/json" \ -b cookies.txt -c cookies.txt \ -d '{ "name": "Task", "fields": { "status": { "type": "Select", "variants": [ "Backlog", "Todo", "In Progress", {"name": "Blocked", "fields": {"blocked_reason": "String"}}, "In Review", "Done" ] }, "priority": "Number", "story_points": "Number", "due_date": "Date", "assignee": "Reference", "project": "Reference", "sprint": "Reference", "labels": { "type": "MultiSelect", "variants": ["Bug", "Feature", "Tech Debt", "Frontend", "Backend", "Infra"] } } }'Create a person, a project referencing that person, and a task referencing both.
# Create a personcurl -X POST https://app.thogits.com/api/thogits \ -H "Content-Type: application/json" \ -b cookies.txt -c cookies.txt \ -d '{ "name": "Alice Chen", "tags": [{ "tag_ref": {"Existing": "PERSON_TAG_ID"}, "field_values": { "department": {"variant": "Engineering"}, "role": "Tech Lead" } }] }'
# Create a project with Alice as leadcurl -X POST https://app.thogits.com/api/thogits \ -H "Content-Type: application/json" \ -b cookies.txt -c cookies.txt \ -d '{ "name": "API Redesign", "tags": [{ "tag_ref": {"Existing": "PROJECT_TAG_ID"}, "field_values": { "name": "API Redesign", "lead": "ALICE_THOGIT_ID", "status": {"variant": "Active"}, "start_date": "2026-04-01", "target_date": "2026-06-30" } }] }'
# Create a task on that project assigned to Alicecurl -X POST https://app.thogits.com/api/thogits \ -H "Content-Type: application/json" \ -b cookies.txt -c cookies.txt \ -d '{ "name": "Design new endpoint schema", "tags": [{ "tag_ref": {"Existing": "TASK_TAG_ID"}, "field_values": { "status": {"variant": "In Progress"}, "priority": 1, "story_points": 5, "due_date": "2026-04-15", "assignee": "ALICE_THOGIT_ID", "project": "PROJECT_THOGIT_ID", "labels": ["Feature", "Backend"] } }] }'With this structure in place, you can write powerful queries like “all high-priority tasks on active projects led by someone in Engineering” using reference traversal:
{ "and": [ {"has_tag": "Task"}, {"Task.priority": {"lte": 2}}, {"Task.project->Project.status": {"match": "Active"}}, {"Task.project->Project.lead->Person.department": {"match": "Engineering"}} ]}