# Store metadata
Source: https://fragment.dev/guides/store-metadata
[Documentation index](https://fragment.dev/llms.txt)
You can provide up to 20 tags on Ledger Entries to store arbitrary key-value pairs, like IDs from your product.
## Schema Entry tags
You can define tags on Ledger Entry types in your Schema:
```json title="Schema-defined tags"
{
"key": "...",
"chartOfAccounts": {...},
"ledgerEntries": {
"types": [
{
"type": "user_funds_account",
"description": "Fund {{user_id}}",
"lines": [
{
"key": "increase_user_balance",
"account": {
"path": "liabilities/users:{{user_id}}/available"
},
"amount": "{{funding_amount}}"
},
{...other line}
],
"tags": [
{
"key": "user",
"value": "{{user_id}}"
},
{
"key": "deposit_flow",
"value": "{{deposit_flow_id}}"
},
{
"key": "deposit_flow_type",
"value": "ach"
}
]
}
]
}
}
```
You can use the same parameter for both tag values and account paths.
When posting a Ledger Entry, include tag values as parameters:
```graphql title="addLedgerEntry mutation" expandable
mutation AddLedgerEntry(
$ik: SafeString!
$entry: LedgerEntryInput!
) {
addLedgerEntry(
ik: $ik,
entry: $entry
) {
__typename
... on AddLedgerEntryResult {
entry {
type
ik
tags {
key
value
}
}
lines {
amount
description
account {
path
}
}
}
... on Error {
code
message
}
}
}
```
```json title="addLedgerEntry variables with Schema-defined tags"
{
"ik": "fund-abc",
"entry": {
"ledger": {
"ik": "quickstart-ledger"
},
"type": "user_funds_account",
"parameters": {
"user_id": "user-1",
"funding_amount": "200",
"deposit_flow_id": "deposit-123"
}
}
}
```
The Ledger Entry will have the tags you defined in the Schema:
```json title="addLedgerEntry response with tags"
{
"data": {
"addLedgerEntry": {
"entry": {
"type": "user_funds_account",
"ik": "fund-abc",
"tags": [
{
"key": "user",
"value": "user-1"
},
{
"key": "deposit_flow",
"value": "deposit-123"
},
{
"key": "deposit_flow_type",
"value": "ach"
}
]
},
"lines": [...]
}
}
}
```
## Runtime Entry tags
You can define tags at runtime when posting a Ledger Entry:
```json title="addLedgerEntry variables with runtime-defined tags"
{
"ik": "add-ledger-entry",
"entry": {
"ledger": {
"ik": "quickstart-ledger"
},
"type": "user_funds_account",
"parameters": {
"user_id": "testing-user",
"funding_amount": "200",
"deposit_flow_id": "abc"
},
"tags": [
{
"key": "deposit_flow_type",
"value": "ach"
},
{
"key": "operator",
"value": "alice"
}
]
}
}
```
If you define tags both at runtime and in the Schema, the Ledger Entry will get the combined set of tags:
```json title="addLedgerEntry response with tags"
{
"data": {
"addLedgerEntry": {
"entry": {
"type": "user_funds_account",
"ik": "fund-abc",
"tags": [
{
"key": "user",
"value": "user-1"
},
{
"key": "deposit_flow",
"value": "deposit-123"
},
{
"key": "deposit_flow_type",
"value": "ach"
},
{
"key": "operator",
"value": "alice"
}
]
},
"lines": [...]
}
}
}
```
You can specify the same tag `key` in both places only if they have the same `value`.
## Updating Entry tags
In addition to tags defined in your Schema, you can add and update tags on a posted Ledger Entry.
```graphql title="updateLedgerEntry mutation" expandable
mutation UpdateLedgerEntryTags(
$ledgerEntry: LedgerEntryMatchInput!
$update: UpdateLedgerEntryInput!
) {
updateLedgerEntry(
ledgerEntry: $ledgerEntry,
update: $update
) {
__typename
... on UpdateLedgerEntryResult {
entry {
type
ik
tags {
key
value
}
lines {
nodes {
amount
description
account {
path
}
}
}
}
}
... on Error {
code
message
}
}
}
```
```json title="updateLedgerEntry variables to add and update tags"
{
"ledgerEntry": {
"ik": "a-ledger-entry",
"ledger": {
"ik": "quickstart-ledger"
}
},
"update": {
"tags": [
{
"key": "operator",
"value": "bob"
},
{
"key": "supervisor",
"value": "eve"
}
]
}
}
```
This is an additive operation:
- If you specify a tag that already exists, it will be updated
- If you specify a new tag, it will be added
- If you don't specify an existing tag, it will remain unchanged
Updating tags will update the Ledger Entry in-place. It will not create a new version of the Ledger Entry.
You can also remove tags from a Ledger Entry using the `tagsToRemove` field:
```json title="updateLedgerEntry variables to remove tags"
{
"ledgerEntry": {
"ik": "a-ledger-entry",
"ledger": {
"ik": "quickstart-ledger"
}
},
"update": {
"tagsToRemove": [
{
"key": "operator",
"value": "bob"
}
]
}
}
```
When removing tags:
- You must specify both the `key` and `value` of the tag to remove
- If the tag doesn't exist, the removal will be ignored
- You cannot remove and update/add the same tag in a single update call
- You must provide at least one tag to remove
You can combine adding/updating and removing tags in a single update:
```json title="updateLedgerEntry variables to add and remove tags"
{
"ledgerEntry": {
"ik": "a-ledger-entry",
"ledger": {
"ik": "quickstart-ledger"
}
},
"update": {
"tags": [
{
"key": "supervisor",
"value": "eve"
}
],
"tagsToRemove": [
{
"key": "operator",
"value": "bob"
}
]
}
}
```
You can only update a Ledger Entry a maximum of 10 times.
## Line tags
You can provide up to 20 tags on individual Ledger Lines to store arbitrary key-value pairs. Line tags are independent of entry-level tags — a Ledger Entry can have its own tags, and each of its lines can have their own tags.
### Schema-defined
You can define tags on lines in your Schema. Tag values support `{{param}}` handlebars syntax, resolved at runtime from entry parameters:
```json title="Schema-defined line tags"
{
"key": "...",
"chartOfAccounts": {...},
"ledgerEntries": {
"types": [
{
"type": "payment",
"description": "Payment to merchant",
"lines": [
{
"key": "debit",
"account": {
"path": "assets/bank"
},
"amount": "{{amount}}",
"tags": [
{
"key": "merchant",
"value": "{{merchant_name}}"
},
{
"key": "category",
"value": "{{category}}"
}
]
},
{
"key": "credit",
"account": {
"path": "liabilities/merchant"
},
"amount": "{{amount}}"
}
]
}
]
}
}
```
When posting a Ledger Entry, include tag values as parameters:
```json title="addLedgerEntry variables with line tags"
{
"ik": "payment-abc",
"entry": {
"ledger": {
"ik": "quickstart-ledger"
},
"type": "payment",
"parameters": {
"amount": "5000",
"merchant_name": "acme-corp",
"category": "software"
}
}
}
```
The Ledger Entry lines will have the tags you defined:
```json title="addLedgerEntry response with line tags"
{
"data": {
"addLedgerEntry": {
"entry": {
"type": "payment",
"ik": "payment-abc",
"tags": []
},
"lines": [
{
"amount": "5000",
"key": "debit",
"account": { "path": "assets/bank" },
"tags": [
{ "key": "merchant", "value": "acme-corp" },
{ "key": "category", "value": "software" }
]
},
{
"amount": "5000",
"key": "credit",
"account": { "path": "liabilities/merchant" },
"tags": []
}
]
}
}
}
```
When using `postLinesAs: "net_amounts"`, lines targeting the same (account, currency, tx) are aggregated into a single line. Tags from aggregated lines are merged:
- Tags with different keys are combined onto the aggregated line
- Tags with the same key and same value are deduplicated
- Tags with the same key but different values cause a `BadRequestError`
- If there are more than 20 tags after merging, the request fails with a `BadRequestError`
### Runtime
When posting a [Runtime Ledger Entry](https://fragment.dev/markdown/guides/post-ledger-entries.md#runtime-entries), you can set tags on each line:
```graphql title="addLedgerEntry mutation with line tags" expandable
mutation AddLedgerEntry(
$ik: SafeString!
$entry: LedgerEntryInput!
) {
addLedgerEntry(
ik: $ik,
entry: $entry
) {
__typename
... on AddLedgerEntryResult {
entry {
ik
tags {
key
value
}
}
lines {
key
amount
account {
path
}
tags {
key
value
}
}
}
... on Error {
code
message
}
}
}
```
```json title="addLedgerEntry variables with runtime line tags"
{
"ik": "payment-abc",
"entry": {
"ledger": {
"ik": "quickstart-ledger"
},
"lines": [
{
"account": { "path": "assets/bank", "ledger": { "ik": "quickstart-ledger" } },
"amount": "5000",
"key": "debit",
"tags": [
{ "key": "merchant", "value": "acme-corp" },
{ "key": "category", "value": "software" }
]
},
{
"account": { "path": "liabilities/merchant", "ledger": { "ik": "quickstart-ledger" } },
"amount": "-5000",
"key": "credit"
}
]
}
}
```
### Repeated Lines
When using [Repeated Lines](https://fragment.dev/markdown/guides/post-ledger-entries.md#repeated-lines), each line gets its own tag values from its array element's parameters:
```json title="Schema with repeated lines and tags"
{
"type": "multi-payment",
"lines": [
{
"key": "payment",
"account": { "path": "assets/bank" },
"amount": "{{amount}}",
"tags": [
{ "key": "merchant", "value": "{{merchant_name}}" },
{ "key": "category", "value": "{{category}}" }
],
"repeated": { "key": "payments" }
}
]
}
```
```json title="Parameters for repeated lines with tags"
{
"payments": [
{ "amount": "10000", "merchant_name": "acme", "category": "software" },
{ "amount": "20000", "merchant_name": "globex", "category": "hardware" }
]
}
```
Each repeated line gets its own tag values:
- Line 1: `merchant=acme, category=software`
- Line 2: `merchant=globex, category=hardware