Skip to content
Sursa Developers

Expanding related objects

Objects refer to related objects by ID: a card has owner_id and collection_id. When you need the related object itself, you do not have to make a second request. Ask for it with expand[], and it comes in the same response, inside expanded:

curl -G https://api.example.com/v1/cards/3f2c9a7e-5b1d-4c8e-9f0a-1b2c3d4e5f60 \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  --data-urlencode "expand[]=owner" \
  --data-urlencode "expand[]=collection"
{
  "id": "3f2c9a7e-5b1d-4c8e-9f0a-1b2c3d4e5f60",
  "title": "Refund policy",
  "owner_id": 7,
  "collection_id": 3,
  "expanded": {
    "owner": {"id": 7, "username": "anna", "display_name": "Anna Petrova", "role": "editor"},
    "collection": {"id": 3, "name": "support", "title": "Support"}
  }
}

The example is shortened: an expanded object has all the fields of its own read operation. The ID fields stay where they are, so code that does not use expand[] sees the same response as before.

These operations expand related objects. A path with a dot expands a link of the expanded object, for example collection.default_owner is the default owner of the card's collection.

OperationPaths
GET /v1/cards/{card_id}, GET /v1/cards-by-external-id/{external_id}collection, owner, verifiers, folders, collection.default_owner
GET /v1/cardsdata.collection, data.owner, data.verifiers, data.folders
GET /v1/jobs/{job_id}card, card.collection, card.owner, card.verifiers, card.folders
GET /v1/jobsdata.card
GET /v1/webhooks/{webhook_id}/deliveries/{delivery_id}event
GET /v1/webhooks/{webhook_id}/deliveriesdata.event
GET /v1/push/sources/{source_id}/documents/{external_id}card, card.collection, card.owner, card.verifiers, card.folders
GET /v1/push/sources/{source_id}/syncs/{sync_number}/documentsdata.card

Each link comes in the form of the operation that reads the related object:

LinkWhat comes in expanded
collectionThe collection, as in GET /v1/collections.
owner, verifiers, default_ownerThe user, as in GET /v1/users: the full row for a caller who may manage users, the brief row (brief=true, active users only) for other callers. verifiers is a list in the order of verifier_ids.
foldersThe folders of the card in its collection that the caller can see, as in GET /v1/folders/{folder_id} without path.
cardThe card, as an item of GET /v1/cards.
eventThe event, as in GET /v1/webhook-events/{event_id}.

In lists

For a list, start the path with data.: it applies to every item of the page. This is the same for a list that returns an array, such as GET /v1/cards, and for a list that keeps its items in a field, such as jobs of GET /v1/jobs or items of the delivery log.

curl -G https://api.example.com/v1/cards \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  --data-urlencode "limit=50" \
  --data-urlencode "expand[]=data.owner" \
  --data-urlencode "expand[]=data.collection"

Sursa loads each link for the whole page at once, so expanding a list costs about as much as one extra request, not one per item. The cursor of the next page does not depend on expand[], so you can ask for other links on the next page.

Rules

  • Up to 10 paths per request, each at most 2 segments deep: data.owner in a list, collection.default_owner on an object.
  • An unknown path, more than 10 paths or a path deeper than 2 segments returns 400 with the code api.expand_invalid. details.path names the path, and details.reason says what is wrong: unknown_path, too_deep or too_many_paths.
  • A related object is expanded only for a caller who could read it with its own request. The key needs the scope of that operation: cards:read for cards, collections and folders, users:read for users, webhooks:manage for events. The object must also be visible to the caller, for example inside the collections of a key that is limited to some collections. Otherwise the link is expanded as null, and in verifiers the user is null in its place. Its ID is still returned. folders lists only the folders that the caller can see.
  • A custom source key does not read cards, so with it card of a document is always null. To get the card, call the push API with an API key that has the import:write and cards:read scopes.
  • An event older than 30 days and the event of a test delivery are expanded as null.
  • expand[] only adds data to the response. It never changes what the request does.