By default, every subject in Tally is visible only to the tenant that owns it. Grants let you share controlled, scoped read access to individual subjects with other tenants on the platform — for example, sharing a KYB-verified entity with a downstream partner, or exposing an individual’s latest identity snapshot to a regulated counterparty. Grants are granular, time-bounded, and fully auditable.
What is a grant?
A grant is a permission record that gives a grantee tenant read access to a specific subject owned by your tenant. The grantee can only exercise the access scopes you explicitly include. Grants do not grant write access — only the owning tenant can ever modify a subject’s snapshots.
Every grant record contains:
- Subject — the
subject_type + subject_id being shared
- Grantee tenant — the
grantee_tenant_id receiving access
- Scopes — which read operations the grantee may perform
- Expiry — an optional
expires_at after which the grant becomes inactive
- Status —
active or revoked
Grant scopes
Scopes let you control exactly what the grantee can do with the shared subject. You can grant any combination of the four available scopes.
| Scope | What it allows |
|---|
read_latest | Read the current (highest-versioned) snapshot |
read_lineage | List snapshot history and read any version by number |
read_snapshot_by_id | Read a specific snapshot by its UUID |
read_diff | Compute attribute diffs between two snapshot versions |
A minimal grant might include only read_latest — enough for a consumer who only needs a current identity check. A more permissive grant for an auditor might include all four scopes.
Creating a grant
Only a tenant_admin or tenant_owner on the owning tenant can create grants.
curl -X POST "https://api.tally.so/v1/tenants/acme-kyc/grants" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"subject_type": "entity",
"subject_id": "ent_acme_001",
"grantee_tenant_id": "partner-bank",
"scopes": ["read_latest", "read_diff"],
"expires_at": "2026-12-31T23:59:59Z"
}'
{
"grant_id": "grnt_7f2a1c94-3d58-4b2e-9c01-1a2b3c4d5e6f",
"subject_type": "entity",
"subject_id": "ent_acme_001",
"grantee_tenant_id": "partner-bank",
"scopes": ["read_latest", "read_diff"],
"expires_at": "2026-12-31T23:59:59.000Z",
"status": "active",
"created_at": "2026-03-01T12:00:00Z",
"created_by": "oidc:https://auth.acme.com#usr_42"
}
Required fields:
| Field | Description |
|---|
subject_type | "entity" or "individual" |
subject_id | The stable subject identifier |
grantee_tenant_id | The tenant receiving access — must already exist in Tally |
scopes | Non-empty array of scope strings |
Optional fields:
| Field | Description |
|---|
expires_at | ISO 8601 datetime after which the grant automatically becomes inactive |
If you omit expires_at, the grant remains active until you explicitly revoke it.
Listing and revoking grants
List all grants for a subject
curl "https://api.tally.so/v1/tenants/acme-kyc/subjects/entity/ent_acme_001/grants" \
-H "Authorization: Bearer <token>"
{
"items": [
{
"grant_id": "grnt_7f2a1c94-3d58-4b2e-9c01-1a2b3c4d5e6f",
"grantee_tenant_id": "partner-bank",
"scopes": ["read_latest", "read_diff"],
"expires_at": "2026-12-31T23:59:59.000Z",
"status": "active",
"created_at": "2026-03-01T12:00:00Z"
}
]
}
Revoke a grant
curl -X POST \
"https://api.tally.so/v1/tenants/acme-kyc/grants/grnt_7f2a1c94-3d58-4b2e-9c01-1a2b3c4d5e6f/revoke" \
-H "Authorization: Bearer <token>"
{
"grant_id": "grnt_7f2a1c94-3d58-4b2e-9c01-1a2b3c4d5e6f",
"status": "revoked",
"revoked_at": "2026-03-15T09:30:00Z",
"revoked_by": "oidc:https://auth.acme.com#usr_42"
}
Grants are append-only records. Revoking a grant sets its status to revoked rather than deleting it, so you always have a full history of who had access to what and when. Once revoked, a grant cannot be re-activated; create a new grant if you need to restore access.
Attempting to revoke a grant that is already revoked or expired returns 409 Conflict.
Accessible subjects
From the grantee side, use the accessible subjects endpoint to list all subjects you have been granted access to:
curl "https://api.tally.so/v1/tenants/partner-bank/accessible-subjects?limit=20" \
-H "Authorization: Bearer <token>"
{
"items": [
{
"subject_type": "entity",
"subject_id": "ent_acme_001",
"scopes": ["read_latest", "read_diff"],
"expires_at": "2026-12-31T23:59:59.000Z",
"access_via": "grant",
"identity_summary": {
"display_name": "Acme Industrial Supply, Inc."
},
"latest_snapshot": {
"snapshot_id": "3f0b2c2c-2e46-4b58-8c45-3b5c58f4e9b2",
"snapshot_version": 3,
"generated_at": "2026-02-20T14:25:30Z"
},
"provenance_summary": {
"evidence_count": 2,
"has_attribute_paths": true,
"has_audit": true
}
}
],
"page": {
"limit": 20,
"next_cursor": null
}
}
The response includes:
identity_summary.display_name — derived from the subject’s canonical attributes
latest_snapshot — the most recent snapshot metadata (not the full envelope)
provenance_summary — quick provenance indicators without fetching the full snapshot
scopes — a reminder of exactly what access you hold
The list is paginated. Pass cursor and limit query parameters to page through results (maximum limit is 200).
Tally enforces one active grant per (subject, grantee_tenant) pair. If
you attempt to create a second active grant for the same subject and grantee,
the API returns 409 Conflict. To change the scopes or expiry on an existing
grant, revoke it first and then create a new grant with the updated
parameters.