Skip to main content

Attributes

Attributes in Anchorpoint are custom metadata that can be attached to files, folders, and tasks to add context and organization to your assets. The Attributes API provides comprehensive functionality to read, write, and manage different types of attributes including tags, text fields, ratings, links, dates, and checkboxes.

Usage​

import apsync
import anchorpoint
from datetime import datetime

ctx = anchorpoint.get_context()
api = anchorpoint.get_api()

# Set a text attribute by name
api.attributes.set_attribute_value(ctx.path, "Description", "Hero character artwork")

# Get a text attribute
description = api.attributes.get_attribute_value(ctx.path, "Description")
print(description) # Output: "Hero character artwork"

# Set a date attribute
api.attributes.set_attribute_value(ctx.path, "Created At", datetime.now())

# Work with attribute objects for more control
attribute = api.attributes.get_attribute("Status")
if not attribute:
attribute = api.attributes.create_attribute("Status", apsync.AttributeType.single_choice_tag)

# Set attribute value using attribute object
api.attributes.set_attribute_value(ctx.path, attribute, "In Progress")

Attribute Types​

Anchorpoint supports several attribute types defined in the AttributeType class:

import apsync

# Available attribute types
apsync.AttributeType.single_choice_tag # Select one tag from predefined options
apsync.AttributeType.multiple_choice_tag # Select multiple tags from predefined options
apsync.AttributeType.text # Free text input
apsync.AttributeType.rating # Numeric rating
apsync.AttributeType.hyperlink # URL or file path links
apsync.AttributeType.date # Date/timestamp values
apsync.AttributeType.checkbox # Boolean true/false values
apsync.AttributeType.user # User attribute

AttributeType Class​

The AttributeType class identifies the type of an attribute.

Members​

  • single_choice_tag Select one tag from predefined options.
  • multiple_choice_tag Select multiple tags from predefined options.
  • text Free text input.
  • rating Numeric rating.
  • hyperlink URL or file path link.
  • date Date value.
  • checkbox Boolean true/false value.
  • user User attribute.

Attributes API​

The Attributes API is accessed through api.attributes and provides methods for creating, managing, and working with attributes.

import anchorpoint

api = anchorpoint.get_api()
attributes = api.attributes

Getting and Setting Attribute Values​

  • api.attributes.get_attribute_value(target, attribute) Retrieves the value of an attribute for a file, folder, or task.

    Arguments

    • target (str or class: Task): Path to the file or folder, or a Task object
    • attribute (class: Attribute or str): The attribute object or attribute name

    Returns: The attribute value, or None

  • api.attributes.set_attribute_value(target, attribute, value, update_timeline=False) Sets the value of an attribute for a file, folder, or task. Creates the attribute if it cannot be found.

    Arguments

    • target (str or class: Task): Path to the file or folder, or a Task object
    • attribute (class: Attribute or str): The attribute object or attribute name
    • value (int, str, list, class: AttributeTag, class: AttributeTagList, bool): Value to set
    • update_timeline (bool, optional): True if the timeline should be notified about the update. Default is False

Managing Attributes​

  • api.attributes.get_attribute(name, type=None) Returns an attribute by name, or None if not found.

    Arguments

    • name (str): Name of the attribute (e.g., "Status")
    • type (class: AttributeType, optional): Attribute type to filter by, or None

    Returns: class: Attribute or None

  • api.attributes.get_attribute_by_id(id) Returns an attribute with a given id.

    Arguments

    • id (str): The id of the attribute

    Returns: class: Attribute

  • api.attributes.get_attributes(type=None) Returns all attributes in the workspace or project, optionally filtered by type.

    Arguments

    • type (class: AttributeType, optional): Attribute type to filter for, or None

    Returns: list[class: Attribute]

  • api.attributes.create_attribute(name, type, tags=None, rating_max=None) Creates a new attribute in the workspace or project.

    Arguments

    • name (str): Name of the attribute (e.g., "Status")
    • type (class: AttributeType): The attribute type
    • tags (class: AttributeTagList or list, optional): List of tags to create, or None
    • rating_max (int, optional): The maximum rating value. Only valid for rating attributes

    Returns: class: Attribute

  • api.attributes.rename_attribute(attribute, name) Renames an attribute.

    Arguments

    • attribute (class: Attribute): The attribute to rename
    • name (str): The new name

Managing Tags​

  • api.attributes.set_attribute_tags(attribute, tags) Sets the available tags for a single or multiple choice tag attribute.

    Arguments

  • api.attributes.set_attribute_rating_max(attribute, max) Sets the maximum rating for a rating attribute.

    Arguments

    • attribute (class: Attribute): The attribute to update
    • max (int): The new maximum rating value

Searching Attributes​

  • api.attributes.search(filter, projects=None, types=None, batch_size=100, changed_since=None, attributes=None, case_insensitive=True, strict=True, workspace_id=None, skip_archived=False)

    Searches attributes across one, several, or all projects in a workspace. The search is lazy: nothing runs until you iterate. Each iteration yields one AttributeSearchBatch scoped to a single project, with at most batch_size items, sorted files first, then folders, then tasks. Projects that match nothing are skipped, so every batch you receive has at least one item.

    Arguments

    • filter (class: AttributeFilter): Built with apsync.attr(...)
    • projects (sequence of str or class: Project, optional): Project ids, project names, or Project objects, in any mix. None searches every project in the workspace. An empty list raises ValueError rather than doing so silently. Pass Project objects built from a local path (apsync.get_project(path) or apsync.create_project(path, ...)) to get batch.project_path and item.absolute_path filled in — ids, names, and the Project objects from get_projects() / get_project_by_id() carry no local root and leave both empty. The same project listed twice is searched once
    • types (list[str], optional): Any of "file", "folder", "task". None means all three
    • batch_size (int, optional): Maximum number of items per batch. Default is 100
    • changed_since (int, optional): Restricts the results to objects that have at least one attribute cell synced at or after this watermark. It selects which objects qualify — the filter is always evaluated against the object's complete set of attribute cells, not only the changed ones. Pass the next_changed_since of a previous search
    • attributes (str or list[str], optional): Which attribute values to return. None returns only the attributes named in the filter, "all" returns every attribute (one extra query per project), and a list returns those attributes. A listed name that no searched project has is reported once in search.warnings, whatever strict says: the argument picks which values come back, never what matches, so naming a superset across projects that hold different attributes is a legitimate way to use it
    • case_insensitive (bool, optional): Fall back to case-insensitive matching when an attribute or tag name has no exact match. Default is True
    • strict (bool, optional): Raise if an attribute, tag, or member name the filter uses is found in no searched project. When False, such a name is reported in search.warnings instead. A name that is merely missing from some projects is neither an error nor a warning — attributes are per project, so most projects of a workspace not having the one you filtered on is normal. Default is True
    • workspace_id (str, optional): Defaults to the workspace set on the API
    • skip_archived (bool, optional): Leave archived projects out of the search, including ones listed explicitly in projects. Default is False, so archived projects are searched

    Returns: class: AttributeSearch

    What the search can match:

    • Only objects that already have at least one attribute value are considered. A file, folder or task with no attribute values at all is never a candidate, so conditions satisfied by absence — is_empty(), not_contains(), equals(False) — return the objects whose other attributes are set and silently omit the untouched ones. There is no way to enumerate "every file without a Status" with this API
    • An | (or) branch naming an attribute that does not exist in a project makes the whole filter unresolvable for that project, so its other branch reports nothing there either. A warning is emitted; with strict=False the search still succeeds. An & (and) behaves the same way, so a filter naming several attributes only reports from projects that have all of them
    • A name that matches two attributes of the same project is ambiguous, and that raises whatever strict says — unlike a name that is merely missing, it is a question the search cannot answer. Scope such a filter with projects to the projects that hold the name once, or rename one of the two attributes
    • Archived projects are searched by default, unlike apsync.get_projects(), which skips them. Pass skip_archived=True to leave them out
    • Relative hyperlink values are returned verbatim unless absolute_path is populated for that item. api.attributes.get_attribute_value always resolves them against the containing folder, so the two can disagree for one cell
    • With strict=True, a name that resolves in no project raises only after the last project has been visited — real batches are yielded first, then the error

    Change detection is limited by what has been synced to this computer:

    • Your own edits are not stamped as they happen. A cell's sync watermark is written during a full resync (on client start, for example), not at the moment of the edit, so a changed_since poll can miss a change this client just made until the next full resync. Changes arriving from other clients are stamped as they sync and are seen normally
    • Deleted objects and deleted cells are removed from the local database, so a changed_since poll can never report a deletion
    • Only attribute cells are matched — renaming or moving a file surfaces nothing
    • Results reflect what has been synced to this computer, not the state on the server
    • The first poll of a pair sees a narrower watermark than the second. Without changed_since only the filtered fields are fetched, so next_changed_since covers just those cells; a follow-up poll fetches every cell and can therefore return an item again because an unrelated attribute of it was newer. Polling never misses a change; it can repeat one

    See Attribute Search below for the filter builder and the result classes.

AttributeTag Class​

The AttributeTag class represents a single or multiple choice tag.

import apsync

tag = apsync.AttributeTag("In Progress", apsync.TagColor.yellow)

Constructor​

  • apsync.AttributeTag(name) Creates a new attribute tag with a default color.

    Arguments

    • name (str): Name of the tag
  • apsync.AttributeTag(name, color) Creates a new attribute tag with a specified color.

    Arguments

    • name (str): Name of the tag
    • color (class: TagColor or str): The color of the tag

Properties​

  • id (str): Unique identifier of the tag.
  • name (str): Name of the tag.
  • color (class: TagColor): The color of the tag.

Attribute Class​

The Attribute class represents an attribute definition. Attributes are not created directly — use api.attributes.get_attribute() or api.attributes.create_attribute() to obtain one.

import apsync
import anchorpoint

api = anchorpoint.get_api()
attribute = api.attributes.get_attribute("Status")
if not attribute:
attribute = api.attributes.create_attribute("Status", apsync.AttributeType.single_choice_tag)

Properties​

  • id (str): Unique identifier for the attribute. Read-only.
  • name (str): Name of the attribute.
  • type (class: AttributeType): Type of the attribute. Read-only.
  • tags (class: AttributeTagList): Available tags for tag-type attributes.
  • rating_max (int or None): Maximum rating value. Only valid for rating attributes.

TagColor Class​

The TagColor class represents the color of a single or multiple choice tag. Use the provided class members instead of raw strings.

import apsync

color = apsync.TagColor.green

Members​

  • red Red color.
  • orange Orange color.
  • yellow Yellow color.
  • green Green color.
  • turk Turquoise color.
  • blue Blue color.
  • purple Purple color.
  • grey Grey color.

Constructor​

  • apsync.TagColor() Creates a default TagColor.

  • apsync.TagColor(color) Creates a TagColor from a string value.

    Arguments

    • color (str): Color string (e.g., "blue", "red")

AttributeTagList Class​

The AttributeTagList class is a list of AttributeTag objects. It behaves like a standard Python list.

import apsync

tags = apsync.AttributeTagList()
tags.append(apsync.AttributeTag("In Progress", apsync.TagColor.yellow))
tags.append(apsync.AttributeTag("Done", apsync.TagColor.green))

Methods​

  • append(x) Adds an item to the end of the list.

    Arguments

  • insert(i, x) Inserts an item at a given position.

    Arguments

    • i (int): The index to insert at
    • x (class: AttributeTag): The tag to insert
  • pop() Removes and returns the last item.

    Returns: class: AttributeTag

  • clear() Clears the contents.

  • extend(L) Extends the list by appending all items from another list.

    Arguments

The attribute search API finds files, folders, and tasks anywhere in a workspace by their attribute values, without touching the filesystem. Build a filter with apsync.attr(...), run it with api.attributes.search(...), and iterate the results in batches. There is no offset-based pagination; instead the search streams results as a lazy iterator, one AttributeSearchBatch at a time, so memory stays bounded no matter how many projects you search.

import apsync as aps

api = aps.get_api()
f = aps.attr("Expedition Tags").contains("Expedition 1 sept")

for batch in api.attributes.search(f, types=["file"]):
for item in batch.items:
print(batch.project_name, item.path)

attr Function​

  • apsync.attr(name) Starts an attribute filter for the attribute with the given name. Returns a builder — call one of its methods (e.g. contains, equals, before) to get a usable AttributeFilter.

    Arguments

    • name (str): The attribute name, as shown in the Anchorpoint UI

    Returns: class: AttributeFilterBuilder

AttributeFilterBuilder Class​

The AttributeFilterBuilder class builds one AttributeFilter condition for a named attribute. You never construct it directly — it is returned by apsync.attr(name). The attribute name is resolved per project when the search runs, so the same condition can be used across a whole workspace.

import apsync as aps

builder = aps.attr("Status")
f = builder.contains("Review")

Properties​

  • name (str): The attribute name passed to apsync.attr(...). Read-only.

Methods​

Matching Text, Tags and Members​

  • contains(values, scope="at_least_one") Matches tag, member, text and hyperlink attributes that contain the given value.

    Arguments

    • values (str or list[str]): A tag name, a member name or email, or search text. A list is matched against tag and member attributes; for text and hyperlink attributes only the first value is used
    • scope (str, optional): "at_least_one" (default) or "all". Only meaningful for multiple choice tag and member attributes

    Returns: class: AttributeFilter

  • not_contains(values, scope="at_least_one") The inverse of contains. Also matches objects that have no value at all.

    Arguments

    • values (str or list[str]): A tag name, a member name or email, or search text
    • scope (str, optional): "at_least_one" (default) or "all"

    Returns: class: AttributeFilter

  • matches_regex(pattern) Matches text, hyperlink, tag and member attributes against a case-insensitive regular expression.

    What the pattern is matched against depends on the attribute:

    • text and hyperlink: the value
    • single and multiple choice tag: the tag names. The condition holds when the object carries at least one tag whose name matches, so there is no scope to choose
    • member: each workspace member's email, full name and nickname

    Tag names belong to a project, so this is how to write one filter for a whole workspace without knowing each project's tags up front. A pattern that matches no tag in a project matches no object there, and — unlike a tag name that does not exist — is not reported as a missing name: a pattern is a query, not an assertion that some tag exists.

    Arguments

    • pattern (str): The regular expression. On a tag or member attribute an invalid pattern raises, because it is compiled while the filter is resolved. On a text or hyperlink attribute it is applied per value and simply matches nothing

    Returns: class: AttributeFilter

    apsync.attr("Expedition Tags").matches_regex(r"Expedition \d+ sept")
    apsync.attr("Reviewer").matches_regex(r"@anchorpoint\.app$")
  • is_empty() Matches text and hyperlink attributes that have no value.

    Returns: class: AttributeFilter

  • is_not_empty() Matches text and hyperlink attributes that have any value.

    Returns: class: AttributeFilter

Matching Any Value​

  • equals(value) Matches text, hyperlink, checkbox and date attributes whose value equals the given one. Dates are compared by day, not by second.

    Arguments

    • value (str, bool, int or datetime): The value to compare against

    Returns: class: AttributeFilter

  • not_equals(value) The inverse of equals.

    Arguments

    • value (str, bool, int or datetime): The value to compare against

    Returns: class: AttributeFilter

Matching Ratings​

  • min(value) Matches rating attributes with at least this many stars.

    Arguments

    • value (int): The lowest rating that still matches

    Returns: class: AttributeFilter

  • max(value) Matches rating attributes with at most this many stars.

    Arguments

    • value (int): The highest rating that still matches

    Returns: class: AttributeFilter

Matching Dates​

  • before(date) Matches date attributes set before the given date.

    Arguments

    • date (datetime or int): The date, or a unix timestamp

    Returns: class: AttributeFilter

  • after(date) Matches date attributes set after the given date.

    Arguments

    • date (datetime or int): The date, or a unix timestamp

    Returns: class: AttributeFilter

  • between(start, end) Matches date attributes inside the closed interval.

    Arguments

    • start (datetime or int): The lower bound, inclusive
    • end (datetime or int): The upper bound, inclusive

    Returns: class: AttributeFilter

  • today() Matches date attributes set to today.

    Returns: class: AttributeFilter

  • this_week() Matches date attributes set to a day in the current week.

    Returns: class: AttributeFilter

  • this_month() Matches date attributes set to a day in the current month.

    Returns: class: AttributeFilter

  • yesterday() Matches date attributes set to yesterday.

    Returns: class: AttributeFilter

  • last_week() Matches date attributes set to a day in the previous week.

    Returns: class: AttributeFilter

  • last_month() Matches date attributes set to a day in the previous month.

    Returns: class: AttributeFilter

  • tomorrow() Matches date attributes set to tomorrow.

    Returns: class: AttributeFilter

  • next_week() Matches date attributes set to a day in the next week.

    Returns: class: AttributeFilter

  • next_month() Matches date attributes set to a day in the next month.

    Returns: class: AttributeFilter

AttributeFilter Class​

The AttributeFilter class represents a single attribute condition, or a tree of them. You never construct it directly — build one with apsync.attr(...) and one of its operand methods.

import apsync as aps

f = aps.attr("Status").contains("Review") & aps.attr("Notes").is_not_empty()

Combining Filters​

  • filter_a & filter_b Combines two filters so both must match (logical AND).
  • filter_a | filter_b Combines two filters so either may match (logical OR).

There is no negation operator. Use the negative operation directly — not_contains, not_equals, is_not_empty — so that a filter can only ever express a condition the attribute actually supports.

AttributeSearch Class​

The AttributeSearch class represents a lazy, cancellable attribute search. You never construct it directly — it is returned by api.attributes.search(...). Iterate it to receive one AttributeSearchBatch per page, or use it as a context manager to cancel automatically when the with block exits.

f = apsync.attr("Status").contains("Review")
with api.attributes.search(f) as search:
for batch in search:
print(batch.project_name, len(batch.items))

Nothing runs until the first iteration. Each instance owns its state and does not hold other Python threads up while it waits, so several searches genuinely run in parallel on several Python threads — but drive one instance from one thread only. cancel() is the only member safe to call from another thread; next_batch, iteration, run, progress, warnings and max_synced_at all touch state that iteration mutates.

Methods​

  • next_batch() Returns the next AttributeSearchBatch, or None when the search is exhausted or was cancelled. Blocks until the next batch is ready, without holding up other Python threads.

    Returns: class: AttributeSearchBatch or None

  • run(callback) Runs the search to completion, calling callback once per batch. Return False from the callback to stop early; any other return value continues.

    Arguments

  • cancel() Stops the search at the next checkpoint. Safe to call from another thread. A query that is already in flight still runs to completion.

Properties​

  • warnings (list[str]): Problems worth your attention, each reported once for the whole search rather than once per project. A project simply not having the attribute you filtered on is not one of them: attributes are per project, so that is the ordinary case for most projects of a workspace. A name shows up here only when no searched project resolved it, and then only with strict False — except for names passed in attributes, which warn either way.
  • progress (tuple[int, int]): Projects finished, projects total.
  • max_synced_at (int): The newest attribute cell sync watermark the search saw, including projects that matched nothing.
  • next_changed_since (int): The value to pass as changed_since on the next poll, or 0 when nothing was seen yet. Equal to max_synced_at + 1, so re-polling with it never returns the same item twice.

AttributeSearchBatch Class​

The AttributeSearchBatch class represents one page of attribute search results, always scoped to a single project. You never construct it directly — you receive it by iterating an AttributeSearch.

for batch in api.attributes.search(f):
print(batch.project_name, len(batch.items))

Properties​

  • project_id (str): The id of the project the items belong to.
  • project_name (str): The name of that project.
  • project_path (str): The local root of that project, or an empty string. Only populated when the caller supplied the root, by passing a Project object built from a local path (apsync.get_project(path) or apsync.create_project(path, ...)) — see absolute_path on AttributeSearchItem.
  • items (list[class: AttributeSearchItem]): The matched objects.
  • max_synced_at (int): The newest sync watermark seen in this project. Use search.next_changed_since for polling, not this value.

AttributeSearchItem Class​

The AttributeSearchItem class represents one object matched by an attribute search — a file, folder, or task. You never construct it directly — you receive it in AttributeSearchBatch.items.

for item in batch.items:
print(item.type, item.path, item.matched_attributes)

Properties​

  • type (str): "file", "folder" or "task".
  • object_id (str): The unique id of the object.
  • path (str): The path relative to the project root, with forward slashes. For a task this is the path of the folder that owns its task list, which is empty for a task list at the project root and also empty when that folder cannot be resolved.
  • absolute_path (str): The absolute path, or an empty string. The search is metadata-only and never reads a project's local root from disk, so this is populated only when the project's root came from the caller — pass a Project object built from a local path, i.e. one returned by apsync.get_project(path) or apsync.create_project(path, ...). Project ids, project names, and the Project objects from get_projects() / get_project_by_id() carry no root and leave this empty. For a task this is the owning folder's absolute path, not the task's.
  • name (str): The file, folder or task name.
  • parent_folder_id (str or None): The id of the containing folder object.
  • task_list_id (str or None): The id of the task list, for tasks.
  • attributes (dict): The attribute values, keyed by attribute name and typed exactly like api.attributes.get_attribute_value returns them. Which attributes appear is controlled by the search's attributes argument.
  • matched_attributes (list[str]): The names of the attributes the filter matched on.
  • revision (int or None): The highest revision among the object's attribute cells — not the object's own revision, so it moves only when an attribute changes.
  • synced_at (int or None): The newest sync watermark across the object's attribute cells that this search queried. With no changed_since the search fetches only the fields named in the filter, so this can be older than the object's true newest watermark.

Standalone Attribute Functions​

These are module-level functions that read and write individual attribute values directly by attribute title, without requiring an Attributes class instance.

Getting Attribute Values​

  • apsync.get_attribute_text(absolute_path, attribute_title, workspace_id=None) Retrieves the text content of an attribute for a given file or folder.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • workspace_id (str, optional): The workspace id, or None

    Returns: str or None

  • apsync.get_attribute_tag(absolute_path, attribute_title, workspace_id=None) Retrieves the tag content of an attribute for a given file or folder.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • workspace_id (str, optional): The workspace id, or None

    Returns: class: AttributeTag or None

  • apsync.get_attribute_tags(absolute_path, attribute_title, workspace_id=None) Retrieves the list of assigned tags of a multiple or single choice tag attribute.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • workspace_id (str, optional): The workspace id, or None

    Returns: list[class: AttributeTag]

  • apsync.get_attribute_rating(absolute_path, attribute_title, workspace_id=None) Retrieves the rating content of an attribute for a given file or folder.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • workspace_id (str, optional): The workspace id, or None

    Returns: int

  • apsync.get_attribute_checked(absolute_path, attribute_title, workspace_id=None) Retrieves the checkbox content of an attribute for a given file or folder.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • workspace_id (str, optional): The workspace id, or None

    Returns: bool

  • apsync.get_attribute_date(absolute_path, attribute_title, workspace_id=None) Retrieves the date content of an attribute for a given file or folder. The date is in seconds since the epoch.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • workspace_id (str, optional): The workspace id, or None

    Returns: int

  • apsync.get_attribute_link(absolute_path, attribute_title, workspace_id=None) Retrieves the link content of an attribute for a given file or folder.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • workspace_id (str, optional): The workspace id, or None

    Returns: str or None

Setting Attribute Values​

  • apsync.set_attribute_text(absolute_path, attribute_title, text, workspace_id=None, auto_create=True, update_timeline=False)

    Sets the text content of an attribute for a given file or folder. Creates the attribute if it cannot be found and auto_create is True.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • text (str): The text to set
    • workspace_id (str, optional): The workspace id, or None
    • auto_create (bool, optional): Automatically create the attribute if it does not exist. Default is True
    • update_timeline (bool, optional): True if the timeline should be notified. Default is False
  • apsync.set_attribute_tag(absolute_path, attribute_title, tag_name, type=AttributeType.single_choice_tag, workspace_id=None, auto_create=True, tag_color=None, update_timeline=False)

    Sets the tag of an attribute for a given file or folder. Creates the attribute if it cannot be found and auto_create is True.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • tag_name (str): The name of the tag to set — creates a new tag if unknown
    • type (class: AttributeType, optional): The type of attribute. Default is single_choice_tag
    • workspace_id (str, optional): The workspace id, or None
    • auto_create (bool, optional): Automatically create the attribute if it does not exist. Default is True
    • tag_color (class: TagColor, optional): The color of the created tag, or None for a random color
    • update_timeline (bool, optional): True if the timeline should be notified. Default is False
  • apsync.set_attribute_tags(absolute_path, attribute_title, tag_names, type=AttributeType.multiple_choice_tag, workspace_id=None, auto_create=True, update_timeline=False)

    Sets the tags of an attribute for a given file or folder, overwriting any existing tags. Creates the attribute if it cannot be found and auto_create is True.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • tag_names (list[str]): The tags to set, identified by name
    • type (class: AttributeType, optional): Must be multiple_choice_tag or single_choice_tag. Default is multiple_choice_tag
    • workspace_id (str, optional): The workspace id, or None
    • auto_create (bool, optional): Automatically create the attribute if it does not exist. Default is True
    • update_timeline (bool, optional): True if the timeline should be notified. Default is False
  • apsync.set_attribute_rating(absolute_path, attribute_title, rating, workspace_id=None, auto_create=True, update_timeline=False)

    Sets the rating content of an attribute for a given file or folder. Creates the attribute if it cannot be found and auto_create is True.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • rating (int): The rating to set
    • workspace_id (str, optional): The workspace id, or None
    • auto_create (bool, optional): Automatically create the attribute if it does not exist. Default is True
    • update_timeline (bool, optional): True if the timeline should be notified. Default is False
  • apsync.set_attribute_checked(absolute_path, attribute_title, checked, workspace_id=None, auto_create=True, update_timeline=False)

    Sets the checkbox content of an attribute for a given file or folder. Creates the attribute if it cannot be found and auto_create is True.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • checked (bool): Check or uncheck the attribute
    • workspace_id (str, optional): The workspace id, or None
    • auto_create (bool, optional): Automatically create the attribute if it does not exist. Default is True
    • update_timeline (bool, optional): True if the timeline should be notified. Default is False
  • apsync.set_attribute_date(absolute_path, attribute_title, secs_since_epoch, workspace_id=None, auto_create=True, update_timeline=False)

    Sets the date content of an attribute for a given file or folder. The date is in seconds since the epoch. Creates the attribute if it cannot be found and auto_create is True.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • secs_since_epoch (int): The date to set in seconds since the epoch
    • workspace_id (str, optional): The workspace id, or None
    • auto_create (bool, optional): Automatically create the attribute if it does not exist. Default is True
    • update_timeline (bool, optional): True if the timeline should be notified. Default is False
  • apsync.set_attribute_link(absolute_path, attribute_title, link, workspace_id=None, auto_create=True, update_timeline=False)

    Sets the link content of an attribute for a given file or folder. A link can point to a website or a file or folder. Creates the attribute if it cannot be found and auto_create is True.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • link (str): The link to set
    • workspace_id (str, optional): The workspace id, or None
    • auto_create (bool, optional): Automatically create the attribute if it does not exist. Default is True
    • update_timeline (bool, optional): True if the timeline should be notified. Default is False

Tag Helpers​

  • apsync.add_attribute_tag(absolute_path, attribute_title, tag_name, type=AttributeType.multiple_choice_tag, workspace_id=None, auto_create=True, tag_color=None, update_timeline=False)

    Adds a tag identified by name to an attribute. If no tags are assigned yet, this is equivalent to set_attribute_tag. Creates the attribute if it cannot be found and auto_create is True.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • tag_name (str): The tag to add, identified by name
    • type (class: AttributeType, optional): Must be multiple_choice_tag or single_choice_tag. Default is multiple_choice_tag
    • workspace_id (str, optional): The workspace id, or None
    • auto_create (bool, optional): Automatically create the attribute if it does not exist. Default is True
    • tag_color (class: TagColor, optional): The color of the created tag, or None
    • update_timeline (bool, optional): True if the timeline should be notified. Default is False
  • apsync.add_attribute_tags(absolute_path, attribute_title, tag_names, type=AttributeType.multiple_choice_tag, workspace_id=None, auto_create=True, update_timeline=False)

    Adds a list of tags identified by name to an attribute. If no tags are assigned yet, this is equivalent to set_attribute_tags. Creates the attribute if it cannot be found and auto_create is True.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • tag_names (list[str]): The tags to add, identified by name
    • type (class: AttributeType, optional): Must be multiple_choice_tag or single_choice_tag. Default is multiple_choice_tag
    • workspace_id (str, optional): The workspace id, or None
    • auto_create (bool, optional): Automatically create the attribute if it does not exist. Default is True
    • update_timeline (bool, optional): True if the timeline should be notified. Default is False
  • apsync.remove_attribute_tag(absolute_path, attribute_title, tag_name, type=AttributeType.multiple_choice_tag, workspace_id=None)

    Removes a tag identified by name from an attribute.

    Arguments

    • absolute_path (str): Path to the file or folder
    • attribute_title (str): Title of the attribute
    • tag_name (str): The tag to remove, identified by name
    • type (class: AttributeType, optional): Must be multiple_choice_tag or single_choice_tag. Default is multiple_choice_tag
    • workspace_id (str, optional): The workspace id, or None

Examples​

Basic Text Attributes​

import apsync
import anchorpoint

ctx = anchorpoint.get_context()
api = anchorpoint.get_api()

# Set a text attribute by name (will auto-create if doesn't exist)
api.attributes.set_attribute_value(ctx.path, "Description", "Hero character concept art for level 1")

# Get the description
description = api.attributes.get_attribute_value(ctx.path, "Description")
print(f"Description: {description}")

Sets a text attribute by name on the current file and reads it back. If the attribute does not exist yet, it is created automatically.

Working with Tags​

import apsync
import anchorpoint

ctx = anchorpoint.get_context()
api = anchorpoint.get_api()

# Create or get a single choice tag attribute
status_attribute = api.attributes.get_attribute("Status")
if not status_attribute:
status_attribute = api.attributes.create_attribute("Status", apsync.AttributeType.single_choice_tag)

# Set up the available tags for this attribute
tags = [
apsync.AttributeTag("In Progress", "blue"),
apsync.AttributeTag("Complete", "green"),
apsync.AttributeTag("On Hold", "orange")
]
api.attributes.set_attribute_tags(status_attribute, tags)

# Set the status value
api.attributes.set_attribute_value(ctx.path, status_attribute, "In Progress")

# Or set using attribute name (simpler for existing attributes)
api.attributes.set_attribute_value(ctx.path, "Status", "Complete")

# Get the current status
current_status = api.attributes.get_attribute_value(ctx.path, "Status")
print(f"Current status: {current_status}")

Creates a single-choice tag attribute called "Status" with three predefined options, sets a value on the current file, and reads it back.

Rating and Review Workflow​

import apsync
import anchorpoint
from datetime import datetime

ctx = anchorpoint.get_context()
api = anchorpoint.get_api()

# Set quality rating (1-5 stars)
api.attributes.set_attribute_value(ctx.path, "Quality", 4)

# Mark as reviewed
api.attributes.set_attribute_value(ctx.path, "Reviewed", True)

# Set review date to current time
api.attributes.set_attribute_value(ctx.path, "Review Date", datetime.now())

# Add reviewer link
api.attributes.set_attribute_value(ctx.path, "Reviewer Profile", "https://company.com/profiles/john.doe")

# Get review information
rating = api.attributes.get_attribute_value(ctx.path, "Quality")
is_reviewed = api.attributes.get_attribute_value(ctx.path, "Reviewed")
review_date = api.attributes.get_attribute_value(ctx.path, "Review Date")

print(f"Rating: {rating}/5 stars")
print(f"Reviewed: {is_reviewed}")
print(f"Review date: {review_date}")

Demonstrates setting multiple attribute types on a single file — a numeric rating, a checkbox, a date, and a hyperlink — then reads them all back.

Batch Processing with Attributes​

import apsync
import anchorpoint
import os
from datetime import datetime

ctx = anchorpoint.get_context()
api = anchorpoint.get_api()

# Process all selected files
for file_path in ctx.selected_files:
filename = os.path.basename(file_path)

# Set common attributes based on file type
if filename.lower().endswith(('.jpg', '.png', '.tiff')):
api.attributes.set_attribute_value(file_path, "Type", "Image")
api.attributes.set_attribute_value(file_path, "Format", "Raster")
elif filename.lower().endswith(('.fbx', '.obj', '.blend')):
api.attributes.set_attribute_value(file_path, "Type", "3D Model")
api.attributes.set_attribute_value(file_path, "Format", "3D Mesh")

# Set processing timestamp
api.attributes.set_attribute_value(file_path, "Processed", datetime.now())

print(f"Processed: {filename}")

Iterates over all selected files and sets "Type" and "Format" attributes based on the file extension, tagging images and 3D models differently.

Creating Complex Attribute Workflows​

import apsync
import anchorpoint

ctx = anchorpoint.get_context()
api = anchorpoint.get_api()

def create_attribute_example():
# This example shows how to access attributes and update the set of tags
attribute = api.attributes.get_attribute("Python Example")
if not attribute:
attribute = api.attributes.create_attribute(
"Python Example", apsync.AttributeType.single_choice_tag
)

new_tag_name = f"Example Tag {len(attribute.tags) + 1}"
tags = attribute.tags
tags.append(apsync.AttributeTag(new_tag_name, "blue"))
api.attributes.set_attribute_tags(attribute, tags)

return attribute

def set_attributes(file_path, example_attribute):
# We can either use the attribute that we have created before ...
latest_tag = example_attribute.tags[-1]
api.attributes.set_attribute_value(file_path, example_attribute, latest_tag)
print(api.attributes.get_attribute_value(file_path, example_attribute))

# ... or create / use attributes described by their title
api.attributes.set_attribute_value(file_path, "Message", "Hello from Python")
print(api.attributes.get_attribute_value(file_path, "Message"))

# To set a date, use datetime.datetime or a unix timestamp
from datetime import datetime
api.attributes.set_attribute_value(file_path, "Created At", datetime.now())

# Create the example attribute
attribute = create_attribute_example()

# Apply to all selected files
for file_path in ctx.selected_files:
set_attributes(file_path, attribute)

Shows a reusable pattern for managing a tag attribute: creates the attribute if it doesn't exist, appends a new tag to its list, then applies both a tag value and a text value to every selected file.

Searching Files by Attribute​

import apsync as aps

api = aps.get_api()

# Find every file across the workspace whose "Expedition Tags" attribute
# contains "Expedition 1 sept"
f = aps.attr("Expedition Tags").contains("Expedition 1 sept")

for batch in api.attributes.search(f, types=["file"]):
for item in batch.items:
print(batch.project_name, item.path)

Searches every project in the workspace for files tagged with a specific expedition, printing the project name and file path for each match. Combine filters with & and | to build more complex conditions, and pass projects=[...] to restrict the search to specific projects.

Working Only With Files That Are On Disk​

import os

import anchorpoint as ap
import apsync as aps

ctx = ap.get_context()
api = ap.get_api()

# absolute_path is only filled in when the project's local root came from you, so
# build the Project from a path rather than passing its name or id.
project = aps.get_project(ctx.project_path)

f = aps.attr("Status").contains("Approved")

for batch in api.attributes.search(f, projects=[project], types=["file"]):
on_disk = [
item
for item in batch.items
if item.absolute_path and os.path.exists(item.absolute_path)
]
for item in on_disk:
print(item.absolute_path)

missing = len(batch.items) - len(on_disk)
if missing:
print(f"{missing} match(es) are not available on this computer")

The search is metadata-only and never reads a project's local root from disk, so a match can be a file that has not been downloaded yet, is not checked out, or was deleted locally. Filtering on os.path.exists is left to you so that you decide when to pay for the filesystem access — one stat per match is cheap on a local disk and slow on a network drive or a large result set.

Two things to know before relying on it. absolute_path is empty unless you passed a Project built from a local path (apsync.get_project(path) or apsync.create_project(path, ...)); project ids, project names, and the Project objects from get_projects() carry no root. And os.path.exists reports a cloud drive placeholder as present even though its contents have not been downloaded, so on a virtual file system this tells you the file is listed, not that it is readable. For a task, absolute_path is the owning folder's path rather than the task's, so this pattern is meant for types=["file"] and types=["folder"].

Polling for Attribute Changes​

import time
import apsync as aps

api = aps.get_api()
f = aps.attr("Status").contains("Approved")

watermark = 0
while True:
search = api.attributes.search(f, changed_since=watermark)
for batch in search:
for item in batch.items:
print("changed:", batch.project_name, item.path)
watermark = search.next_changed_since or watermark
time.sleep(60)

Polls for files whose "Status" attribute was set to "Approved" since the last check. changed_since only restricts which objects are reported — the filter always evaluates against each object's full set of attributes, not just the changed ones. Always feed search.next_changed_since (not max_synced_at) into the next poll, since it already accounts for the inclusive comparison. Because this reports only what has been synced to this computer: your own not-yet-resynced edits are not visible, deletions can never be reported this way, and only attribute changes — not renames or moves — are detected.