Custodian Authorities
Data Model
Custodian Authority
A custodian authority represents the lifecycle of granting Aleta access to a custodian on behalf of a legal entity.
status(string, required): Current status in the custodian authority lifecycle. One of:waiting-for-files— The custodian authority has been created. Required files (listed inpendingFiles) must be uploaded viaPOST /custodian-authorities/:id/files.waiting-for-consent— All required files have been uploaded. The consent details must now be submitted as a JSON document viaPOST /custodian-authorities/:id/consent.awaiting-aleta— Consent has been submitted (or the custodian has responded). Aleta is reviewing / processing.awaiting-custodian— Aleta has forwarded the request to the custodian. Waiting for the custodian to act. The status may alternate betweenawaiting-aletaandawaiting-custodianmultiple times.active— The custodian authority is fully established and dataflow is operational.revoke-in-progress— A revocation has been requested. Aleta is removing dataflow links with the custodian.revoked— The custodian authority has been fully revoked. Dataflow has stopped.cancelled— The custodian authority was cancelled before becoming active (e.g. rejected by the custodian).
pendingFiles(array, required): List of file names that still need to be uploaded before consent can be submitted. Only populated when status iswaiting-for-files. Empty array otherwise. File names correspond to those defined in the custodian auth flow'sexpectedFiles.linkedDepositories(array, required): Depositories linked to this custodian authority. Each entry contains:depositoryNumber(string): The depository number as it appears at the custodian.depositoryId(string, nullable): The Aleta depository ID. Null while the depository is being set up (statusin-progress), populated onceactive.status(string): Status of the linked depository. One of:in-progress— The depository link has been requested. Aleta is setting up the dataflow connection with the custodian. ThedepositoryIdis null during this state.active— The depository is fully linked and dataflow is operational. ThedepositoryIdis populated.
linkedAccounts(array, required): Accounts linked to this custodian authority. Each entry contains:accountNumber(string): The account number as it appears at the custodian.accountId(string, nullable): The Aleta account ID. Null while the account is being set up (statusin-progress), populated onceactive.status(string): Status of the linked account. One of:in-progress— The account link has been requested. Aleta is setting up the dataflow connection with the custodian. TheaccountIdis null during this state.active— The account is fully linked and dataflow is operational. TheaccountIdis populated.
Relationships
custodian: The custodian that the authority relates to.custodianAuthFlow: The custodian auth flow used to create the authority.legalEntity: The legal entity that the authority is granted for.
Custodian Authority File
A file uploaded for a custodian authority. Files serve as proof of access and cannot be deleted.
hash(string): Content hash prefixed with the algorithm (e.g.sha2-256:7d865e...). When constructing the consent request'sfilesarray for thePOST /custodian-authorities/:id/consentendpoint, split this value on the:separator: use the prefix (e.g.sha2-256) ashashAlgorithmand the raw hexadecimal digest ashashValue.name(string): Logical name identifying the role of the file (e.g.power-of-attorney,consent). Matches one of the custodian auth flow'sexpectedFiles.uploadedAt(string, ISO 8601): UTC timestamp of when the file was uploaded.filename(string): Original filename as provided by the uploader.
Endpoints
GET /legal-entities/:legalEntityId/custodian-authorities
Not yet available.
List all custodian authorities for a given legal entity.
Parameters
legalEntityId(path, required): Identifier for the legal entity.
Examples
200 OK
# Request
GET /api/v2/legal-entities/67b01234a5bc678d90e12345/custodian-authorities HTTP/1.1
Accept: application/vnd.api+json
Authorization: Bearer <access token>
Host: platform.aleta.io
# Response
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": [
{
"id": "2668e473-b2a2-47a9-a90b-a5ec0c812d44",
"type": "custodian-authority",
"attributes": {
"status": "active",
"pendingFiles": [],
"linkedDepositories": [
{
"depositoryNumber": "1234-5678901234",
"depositoryId": "67c01234a5bc678d90e12345",
"status": "active"
},
{
"depositoryNumber": "1234-5678901235",
"depositoryId": null,
"status": "in-progress"
}
],
"linkedAccounts": [
{
"accountNumber": "1234-0011223344",
"accountId": "67c01234a5bc678d90e12346",
"status": "active"
}
]
},
"relationships": {
"custodian": {
"data": {
"type": "custodian",
"id": "678e9012f3ab456c78d90123"
}
},
"custodianAuthFlow": {
"data": {
"type": "custodian-auth-flow",
"id": "nordea-20260630"
}
},
"legalEntity": {
"data": {
"type": "legal-entity",
"id": "67b01234a5bc678d90e12345"
}
}
}
},
{
"id": "ac8fa31f-b9bd-414c-a56d-8d95848ebbcf",
"type": "custodian-authority",
"attributes": {
"status": "waiting-for-files",
"pendingFiles": [
"power-of-attorney",
"consent"
],
"linkedDepositories": [],
"linkedAccounts": []
},
"relationships": {
"custodian": {
"data": {
"type": "custodian",
"id": "679a2345b6cd789e01f23456"
}
},
"custodianAuthFlow": {
"data": {
"type": "custodian-auth-flow",
"id": "saxo-20260630"
}
},
"legalEntity": {
"data": {
"type": "legal-entity",
"id": "67b01234a5bc678d90e12345"
}
}
}
}
]
}
POST /legal-entities/:legalEntityId/custodian-authorities
Not yet available.
Create a custodian authority for a given legal entity using the specified custodian auth flow.
The new custodian authority is created in the waiting-for-files status. Upload the required
files (listed in pendingFiles) using the POST /custodian-authorities/:id/files endpoint to
advance to waiting-for-consent.
Parameters
legalEntityId(path, required): Identifier for the legal entity.custodianAuthFlowId(query, required): The custodian auth flow identifier.
Examples
201 Created
# Request
POST /api/v2/legal-entities/67b01234a5bc678d90e12345/custodian-authorities
?custodianAuthFlowId=nordea-20260630 HTTP/1.1
Accept: application/vnd.api+json
Authorization: Bearer <access token>
Host: platform.aleta.io
# Response
HTTP/1.1 201 Created
Content-Type: application/vnd.api+json
{
"data": {
"id": "2668e473-b2a2-47a9-a90b-a5ec0c812d44",
"type": "custodian-authority",
"attributes": {
"status": "waiting-for-files",
"pendingFiles": [
"power-of-attorney",
"consent"
],
"linkedDepositories": [],
"linkedAccounts": []
},
"relationships": {
"custodian": {
"data": {
"type": "custodian",
"id": "678e9012f3ab456c78d90123"
}
},
"custodianAuthFlow": {
"data": {
"type": "custodian-auth-flow",
"id": "nordea-20260630"
}
},
"legalEntity": {
"data": {
"type": "legal-entity",
"id": "67b01234a5bc678d90e12345"
}
}
}
}
}
400 Bad Request
Returned when the custodian auth flow ID is outdated. Use the latest custodian auth flow for onboarding.
404 Not Found
Returned when the custodian auth flow ID or legal entity ID does not exist.
GET /custodian-authorities/:id
Not yet available.
Get a custodian authority by its id.
Parameters
id(path, required): Custodian authority identifier.
Examples
200 OK
# Request
GET /api/v2/custodian-authorities/2668e473-b2a2-47a9-a90b-a5ec0c812d44 HTTP/1.1
Accept: application/vnd.api+json
Authorization: Bearer <access token>
Host: platform.aleta.io
# Response
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": {
"id": "2668e473-b2a2-47a9-a90b-a5ec0c812d44",
"type": "custodian-authority",
"attributes": {
"status": "active",
"pendingFiles": [],
"linkedDepositories": [
{
"depositoryNumber": "1234-5678901234",
"depositoryId": "67c01234a5bc678d90e12345",
"status": "active"
}
],
"linkedAccounts": [
{
"accountNumber": "1234-0011223344",
"accountId": "67c01234a5bc678d90e12346",
"status": "active"
}
]
},
"relationships": {
"custodian": {
"data": {
"type": "custodian",
"id": "678e9012f3ab456c78d90123"
}
},
"custodianAuthFlow": {
"data": {
"type": "custodian-auth-flow",
"id": "nordea-20260630"
}
},
"legalEntity": {
"data": {
"type": "legal-entity",
"id": "67b01234a5bc678d90e12345"
}
}
}
}
}
POST /custodian-authorities/:id/files
Not yet available.
Upload a file for a custodian authority. The file name is specified via the name query parameter.
Supported names are defined by the custodian auth flow (e.g. power-of-attorney, consent, back-office-login).
The returned hash is prefixed with the algorithm used (e.g. sha2-256: or sha3-256:) and serves as proof of file content for the POST /custodian-authorities/:id/consent endpoint.
Once all required files have been uploaded, the custodian authority status transitions
from waiting-for-files to waiting-for-consent and pendingFiles becomes empty.
Parameters
id(path, required): Custodian authority identifier.name(query, required): Name of the file (e.g.power-of-attorney,consent,back-office-login). Must match one of the names defined in the custodian auth flow'sexpectedFiles.
Request Body
The request body must be multipart/form-data with a single file field containing the file to upload.
Examples
201 Created
# Request
POST /api/v2/custodian-authorities/2668e473-b2a2-47a9-a90b-a5ec0c812d44/files
?name=power-of-attorney HTTP/1.1
Accept: application/vnd.api+json
Authorization: Bearer <access token>
Content-Type: multipart/form-data; boundary=----FormBoundary
Host: platform.aleta.io
------FormBoundary
Content-Disposition: form-data; name="file"; filename="poa_nordea_2026.pdf"
Content-Type: application/pdf
<binary file content>
------FormBoundary--
# Response
HTTP/1.1 201 Created
Content-Type: application/vnd.api+json
{
"data": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"type": "custodian-authority-file",
"attributes": {
"hash": "sha2-256:7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730",
"name": "power-of-attorney",
"uploadedAt": "2026-03-01T10:00:00Z",
"filename": "poa_nordea_2026.pdf"
}
}
}
GET /custodian-authorities/:id/files
Not yet available.
List all files uploaded for a custodian authority, including their name, hash, upload timestamp, and original filename. Files cannot be deleted, as they serve as proof of access.
Parameters
id(path, required): Custodian authority identifier.
Examples
200 OK
# Request
GET /api/v2/custodian-authorities/2668e473-b2a2-47a9-a90b-a5ec0c812d44/files HTTP/1.1
Accept: application/vnd.api+json
Authorization: Bearer <access token>
Host: platform.aleta.io
# Response
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": [
{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"type": "custodian-authority-file",
"attributes": {
"hash": "sha2-256:7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730",
"name": "power-of-attorney",
"uploadedAt": "2026-03-01T10:00:00Z",
"filename": "poa_nordea_2026.pdf"
}
},
{
"id": "f6e5d4c3-b2a1-4f0e-9d8c-7b6a5f4e3d2c",
"type": "custodian-authority-file",
"attributes": {
"hash": "sha2-256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"name": "consent",
"uploadedAt": "2026-03-01T10:01:00Z",
"filename": "consent_nordea_2026.pdf"
}
}
]
}
POST /custodian-authorities/:id/consent
Not yet available.
Submit the consent details as a JSON document. The custodian authority must be in waiting-for-consent status (i.e. all required files have been uploaded). On success, the status transitions to awaiting-aleta.
The consent is submitted as a plain JSON:API document over the authenticated channel — the caller's identity and authorization are established by the bearer token, so the payload is not separately signed.
Parameters
id(path, required): Custodian authority identifier.
Request Body
A JSON:API document whose data object contains the consent details:
legalEntityIdentifier(string, required): Identifier of the legal entity (e.g. CVR, CPR).custodianIdentifier(string, required): Theidentifierattribute from the custodian object.consentType(string, required): Type of consent. Possible values:"all","specific".files(array, required): Array of objects, each with aname(matching the file name used during upload), ahashAlgorithm(sha2-256orsha3-256) and ahashValue(the raw hexadecimal digest). Derive these from the file'shashby splitting on the:separator.depositoryNumbers(array, optional): List of depository numbers. Used whenconsentTypeis"specific".accountNumbers(array, optional): List of account numbers. Used whenconsentTypeis"specific".
Examples
204 No Content — Specific consent
# Request
POST /api/v2/custodian-authorities/2668e473-b2a2-47a9-a90b-a5ec0c812d44/consent HTTP/1.1
Authorization: Bearer <access token>
Content-Type: application/vnd.api+json
Host: platform.aleta.io
{
"data": {
"legalEntityIdentifier": "12345678",
"custodianIdentifier": "nordea-dk",
"consentType": "specific",
"files": [
{
"name": "consent",
"hashAlgorithm": "sha2-256",
"hashValue": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
{
"name": "power-of-attorney",
"hashAlgorithm": "sha2-256",
"hashValue": "7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730"
}
],
"depositoryNumbers": ["2345-6789012345", "2345-6789012346"],
"accountNumbers": ["2345-0011223344", "2345-0011223345"]
}
}
# Response
HTTP/1.1 204 No Content
204 No Content — All consent
For consent type all, omit depositoryNumbers and accountNumbers — the consent covers every depository and account at the custodian for the legal entity.
# Request
POST /api/v2/custodian-authorities/2668e473-b2a2-47a9-a90b-a5ec0c812d44/consent HTTP/1.1
Authorization: Bearer <access token>
Content-Type: application/vnd.api+json
Host: platform.aleta.io
{
"data": {
"legalEntityIdentifier": "12345678",
"custodianIdentifier": "nordea-dk",
"consentType": "all",
"files": [
{
"name": "consent",
"hashAlgorithm": "sha2-256",
"hashValue": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
{
"name": "power-of-attorney",
"hashAlgorithm": "sha2-256",
"hashValue": "7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730"
}
]
}
}
# Response
HTTP/1.1 204 No Content
400 Bad Request — Duplicate "all" consent
A legal entity may only have one custodian authority with consent type all per custodian.
# Request
POST /api/v2/custodian-authorities/2668e473-b2a2-47a9-a90b-a5ec0c812d44/consent HTTP/1.1
Authorization: Bearer <access token>
Content-Type: application/vnd.api+json
Host: platform.aleta.io
{
"data": {
"legalEntityIdentifier": "12345678",
"custodianIdentifier": "nordea-dk",
"consentType": "all",
"files": [
{
"name": "consent",
"hashAlgorithm": "sha2-256",
"hashValue": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
]
}
}
# Response
HTTP/1.1 400 Bad Request
Content-Type: application/vnd.api+json
{
"errors": [
{
"status": 400,
"detail": "A custodian authority with consent type 'all' already exists for this legal entity and custodian."
}
]
}
400 Bad Request — Overlapping "specific" consent
For consent type specific, multiple custodian authorities are allowed per legal entity and custodian combination, but the depository numbers and account numbers must not overlap with any existing custodian authority.
# Request
POST /api/v2/custodian-authorities/2668e473-b2a2-47a9-a90b-a5ec0c812d44/consent HTTP/1.1
Authorization: Bearer <access token>
Content-Type: application/vnd.api+json
Host: platform.aleta.io
{
"data": {
"legalEntityIdentifier": "12345678",
"custodianIdentifier": "nordea-dk",
"consentType": "specific",
"files": [
{
"name": "consent",
"hashAlgorithm": "sha2-256",
"hashValue": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
],
"depositoryNumbers": ["2345-6789012345"]
}
}
# Response
HTTP/1.1 400 Bad Request
Content-Type: application/vnd.api+json
{
"errors": [
{
"status": 400,
"detail": "One or more depository numbers or account numbers overlap with an existing custodian authority for this legal entity and custodian."
}
]
}
POST /custodian-authorities/:id/link
Not yet available.
Link a depository or account to a custodian authority. This is only supported for custodian authorities with consent type all.
If you want to add depositories or accounts to a custodian authority with consent type specific, create a new custodian authority with the additional depositories or accounts instead.
Parameters
id(path, required): Custodian authority identifier.type(query, required): The type of resource to link. Possible values:"depository","account".resourceNumber(query, required): The depository number or account number to link to this custodian authority.
Examples
204 No Content
# Request
POST /api/v2/custodian-authorities/2668e473-b2a2-47a9-a90b-a5ec0c812d44/link
?type=depository
&resourceNumber=1234-5678901235 HTTP/1.1
Authorization: Bearer <access token>
Host: platform.aleta.io
# Response
HTTP/1.1 204 No Content
400 Bad Request — Invalid consent type
Returned when attempting to link a depository or account to a custodian authority that does not have consent type all.
# Request
POST /api/v2/custodian-authorities/ac8fa31f-b9bd-414c-a56d-8d95848ebbcf/link
?type=depository
&resourceNumber=1234-5678901235 HTTP/1.1
Authorization: Bearer <access token>
Host: platform.aleta.io
# Response
HTTP/1.1 400 Bad Request
Content-Type: application/vnd.api+json
{
"errors": [
{
"status": 400,
"detail": "Linking is only supported for custodian authorities with consent type 'all'."
}
]
}
POST /custodian-authorities/:id/revoke
Not yet available.
Initiate revocation of a custodian authority. This endpoint takes no request body.
Returns a JSON confirmation of the revocation request. Aleta then removes the dataflow links between the depositories/accounts and the custodian; the status moves to revoke-in-progress and, once complete, to revoked.
Poll GET /custodian-authorities/:id to track the status.
Response Body
A JSON:API document whose data object confirms the revocation request:
custodianAuthorityId(string): The custodian authority ID.status(string): The status of the custodian authority for the revocation request.
Parameters
id(path, required): Custodian authority identifier.
Request Body
None. The request body is ignored.
Examples
200 OK
# Request
POST /api/v2/custodian-authorities/2668e473-b2a2-47a9-a90b-a5ec0c812d44/revoke HTTP/1.1
Authorization: Bearer <access token>
Host: platform.aleta.io
# Response
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": {
"custodianAuthorityId": "2668e473-b2a2-47a9-a90b-a5ec0c812d44",
"status": "revoke-in-progress"
}
}