Skip to main content
A refresh request is a formal signal from a grantee (or from the owner itself) asking the subject owner to publish a newer identity snapshot. Rather than polling for updates, your counterparty sends a refresh request — optionally specifying which attributes they care about — and you fulfill it once you’ve applied a new patch and have a fresh snapshot to point to. The whole flow is auditable: every request carries a status, timestamps, and the resolved snapshot ID once fulfilled.

Create a refresh request

POST /v1/subjects/:subject_type/:subject_id/refresh-requests Creates a new refresh request for the given subject. The server derives origin_type automatically: if your tenant owns the subject the value is "owner", otherwise it is "counterparty". You cannot set origin_type yourself — passing it returns 400 Bad Request. The calling principal must be an active member of requesting_tenant_id with at least the tenant_reader role, and that tenant must either own the subject or hold an active grant for it.

Path parameters

subject_type
string
required
Must be entity or individual.
subject_id
string
required
The identifier of the subject.

Body parameters

requesting_tenant_id
string
required
The ID of the tenant on whose behalf the request is being made.
reason_code
string
An optional machine-readable code describing why the refresh is needed (e.g. "annual_review", "aml_alert", "onboarding").
message
string
An optional human-readable message to accompany the request.
requested_paths
array of strings
An optional list of JSON Pointers identifying the specific attributes you need updated (e.g. ["/attributes/registered_address", "/attributes/directors"]). Duplicates are deduplicated. Each path must start with /.
expires_at
string (ISO 8601)
An optional deadline after which the request is no longer relevant. The owner’s system may use this to prioritise urgent requests.

Response

201 Created
{
  "refresh_request": {
    "refresh_request_id": "rr_11223344-aaaa-bbbb-cccc-001122334455",
    "subject": { "subject_type": "entity", "subject_id": "ent_7f3a1b2c" },
    "requesting_tenant_id": "partner-bank",
    "origin_type": "counterparty",
    "status": "pending",
    "reason_code": "annual_review",
    "message": "Please update the registered address.",
    "requested_paths": ["/attributes/registered_address"],
    "created_at": "2024-06-20T10:00:00.000Z",
    "expires_at": "2024-07-20T10:00:00.000Z",
    "resolved_at": null,
    "resolved_snapshot_id": null,
    "resolved_snapshot_version": null
  }
}

Get a refresh request

GET /v1/subjects/:subject_type/:subject_id/refresh-requests/:refresh_request_id Returns a single refresh request by ID. Access requires one of: you are a member of the subject’s owning tenant, or you are a member of the requesting_tenant_id tenant and that tenant holds an active grant for the subject.

Path parameters

subject_type
string
required
Must be entity or individual.
subject_id
string
required
The identifier of the subject.
refresh_request_id
string (UUID)
required
The ID of the refresh request.

Response

200 OK{ refresh_request: RefreshRequestRow }

List refresh requests

GET /v1/subjects/:subject_type/:subject_id/refresh-requests Returns a paginated list of refresh requests for a subject.
  • Subject owners may list all requests or filter by requesting_tenant_id.
  • Grantees must supply their own requesting_tenant_id — they can only see their own requests.

Path parameters

subject_type
string
required
Must be entity or individual.
subject_id
string
required
The identifier of the subject.

Query parameters

requesting_tenant_id
string
Filter results to only requests from this tenant. Required if the calling principal is not a member of the subject’s owning tenant.
limit
integer
Number of results per page. Between 1 and 200. Defaults to 50.
cursor
string
Opaque pagination cursor from the previous response’s page.next_cursor.

Response

200 OK
{
  "items": [ /* RefreshRequest objects */ ],
  "page": {
    "limit": 50,
    "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNC0wNi0yMFQxMDowMDowMC4wMDBaIiwicmVmcmVzaF9yZXF1ZXN0X2lkIjoicnJfMTEyMjMzNDQtYWFhYS1iYmJiLWNjY2MtMDAxMTIyMzM0NDU1In0"
  }
}

Fulfill a refresh request

POST /v1/subjects/:subject_type/:subject_id/refresh-requests/:refresh_request_id/fulfill Links a published snapshot to a pending refresh request, transitioning it to "fulfilled". You should call this after you have applied an entity state update that addresses the request (see State Updates). Only members of the subject’s owning tenant may call this endpoint.

Path parameters

subject_type
string
required
Must be entity or individual.
subject_id
string
required
The identifier of the subject.
refresh_request_id
string (UUID)
required
The ID of the refresh request to fulfill.

Body parameters

resolved_snapshot_id
string (UUID)
required
The snapshot_id of the new snapshot that fulfills this request. Must belong to the same subject.

Response

200 OK — the updated refresh request with status: "fulfilled", resolved_at, resolved_snapshot_id, and resolved_snapshot_version populated.
{
  "refresh_request": {
    "refresh_request_id": "rr_11223344-aaaa-bbbb-cccc-001122334455",
    "status": "fulfilled",
    "resolved_at": "2024-06-21T08:45:00.000Z",
    "resolved_snapshot_id": "e9d8c7b6-9999-0000-abcd-ffeeddccbbaa",
    "resolved_snapshot_version": 6
  }
}

Error responses

StatusCodeMeaning
403forbiddenOnly the subject owner can fulfill a refresh request.
404not_foundNo refresh request exists with this ID.
409conflictThe request is already fulfilled, the snapshot doesn’t match the subject, or the snapshot was previously linked to a different snapshot ID.

Full flow example

# Partner-bank calls this as a grantee that holds an active grant
curl -X POST \
  "https://api.tally.so/v1/subjects/entity/ent_7f3a1b2c/refresh-requests" \
  -H "Authorization: Bearer $PARTNER_BANK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "requesting_tenant_id": "partner-bank",
    "reason_code": "annual_review",
    "message": "Please update registered address for annual KYC review.",
    "requested_paths": ["/attributes/registered_address"],
    "expires_at": "2024-07-20T00:00:00.000Z"
  }'
# → 201 { "refresh_request": { "refresh_request_id": "rr_...", "status": "pending", ... } }
Subscribe to the refresh_request.created webhook event (see Webhooks) to be notified immediately when a grantee creates a refresh request for one of your subjects, so you can action it promptly without polling.