Skip to content
Sursa Developers

Metadata

metadata is a set of your own key-value pairs on an object: the ID of the record in your CRM, the team that owns it, the run of the sync that wrote it. Sursa stores it, returns it with the object and in events, and lets you filter the lists of cards, collections and folders by it. It does not interpret it in any way.

{
  "id": "3f2c9a7e-5b1d-4c8e-9f0a-1b2c3d4e5f60",
  "title": "Refund policy",
  "metadata": {"crm_id": "A-1042", "team": "support"}
}

Objects with metadata: cards, collections and folders. A document of a custom source carries metadata too; it becomes the metadata of the document's card.

Limits

LimitValue
Pairs per object50
Key1 to 40 characters from A-Z, a-z, 0-9, _, . and -, starting with a letter or a digit
ValueA string of up to 500 characters
The whole objectUp to 8 KiB as JSON

A request that breaks a limit returns 400 with the code api.metadata_invalid. error.details.key names the key, and error.details.reason says what is wrong: too_many_keys, key_invalid, value_too_long, too_large or value_invalid (the value is not a string).

Values are strings. Store numbers and dates as strings too, for example "2026-10-24".

Set metadata

When you create or replace an object (POST, PUT), metadata is set as a whole:

curl -X PUT https://api.sursa.com/v1/cards-by-external-id/policy-refunds \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Refund policy",
    "body": "Refunds are processed within 14 days.",
    "metadata": {"crm_id": "A-1042", "team": "support"}
  }'

In a multipart/form-data request, such as a file upload, send metadata as a form field whose value is the JSON object: metadata={"crm_id":"A-1042"}.

Update metadata

PATCH merges the keys you send into the existing ones. A key with the value "" or null is removed; keys you do not send stay as they are:

curl -X PATCH https://api.sursa.com/v1/cards/3f2c9a7e-5b1d-4c8e-9f0a-1b2c3d4e5f60 \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"metadata": {"team": "billing", "legacy_flag": null}}'
{"id": "3f2c9a7e-5b1d-4c8e-9f0a-1b2c3d4e5f60", "title": "Refund policy", "metadata": {"crm_id": "A-1042", "team": "billing"}}

"metadata": {} changes nothing. To remove all pairs, send each key with null.

Filter by metadata

These lists accept metadata[<key>]=<value>:

It matches the value exactly. You can combine up to 3 conditions, and an object must match all of them:

curl -G https://api.sursa.com/v1/cards \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  --data-urlencode "metadata[team]=support" \
  --data-urlencode "metadata[crm_id]=A-1042"

With a filter, a folder tree comes as a flat list: folders of each collection holds the matching folders with empty children, and parent_id tells where each one sits. GET /v1/folders then leaves out the collections without matching folders. More than 3 conditions or an invalid key returns 400 with the code api.metadata_invalid.

What metadata is not

  • It is not content. Search and the assistant's answers do not use it. Put what people should find into the text of the card, its title or its tags.
  • It is not private. Everyone who can see the object can see its metadata. Never store secrets, tokens or personal data that the object's readers should not see.
  • It is not a substitute for external_id. To find a card by the ID of your record, give the card an external_id; it is unique, while metadata values are not.