API Reference
The Coanda API is organized around REST. Our Api has predictable resource-oriented URLs, accepts JSON-encoded request bodies, returns JSON-encoded responses and uses standard HTTP response codes, authentication and verbs.
You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.
Please read the Authentication chapter first.
Authentication
To authorize, use this code:
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here"
-H "Authorization: Bearer myToken"
Make sure to replace
myTokenwith the generated token.
Coanda uses JWT tokens to allow access to the API.
Coanda expects for the JWT token to be included in all API requests to the server in a header that looks like the following:
Authorization: Bearer myToken
Generate an authorization token (deprecated)
curl "https://aaaic-backend.ppd.rafa.3a-digital.fr/user-service/v1/token/acquire?username=myuser%40test.com&password=testpassword"
-H "accept: text/plain"
The above command returns the JWT token as a raw string in the response body:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.dyt0CoTl4WoVjAHI9Q_CwSKhl6d_9rhM3NrXuJttkao
This endpoint generate a JWT token from a combination of username and password.
HTTP Request
GET /user-service/v1/token/acquire
URL Parameters
| Parameter | Description |
|---|---|
| username | Your username/clientId. Must be sent url_encoded. |
| password | Your password/clientSecret. Must be sent url_encoded. |
Generate an authorization token (OAuth)
curl --request POST \
--url "https://aaaic-backend.ppd.rafa.3a-digital.fr/user-service/v1/token/oauth" \
--header "content-type: application/x-www-form-urlencoded" \
--data grant_type=client_credentials \
--data client_id=YOUR_CLIENT_ID \
--data client_secret=YOUR_CLIENT_SECRET
The above command returns a JSON response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.dyt0CoTl4WoVjAHI9Q_CwSKhl6d_9rhM3NrXuJttkao",
"token_type": "Bearer"
}
This endpoint generates a JWT token using the OAuth 2.0 Client Credentials flow.
HTTP Request
POST /user-service/v1/token/oauth
Request Body (application/x-www-form-urlencoded)
| Parameter | Description |
|---|---|
| grant_type | Must be set to client_credentials. |
| client_id | Your client identifier. |
| client_secret | Your client secret. |
Response
| Field | Description |
|---|---|
| access_token | The generated JWT token. |
| token_type | The token type. Always Bearer. |
Simulator Module
The simulator module offers several endpoint to perform various computations on a saving project. The three main endpoints are each dedicated to a specific management mode (free, delegated and glidepath).
Free Management
curl \
--location 'https://aaaic-backend.ppd.rafa.3a-digital.fr/simulator-service/simulator/free_management' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <myToken>' \
--data '{
"simulation_start_date": "202008",
"simple_deposits": [
{
"amount": 5000,
"date": "202010"
}
],
"periodic_deposits": [
{
"amount": 197.2,
"start_date": "202008",
"end_date": "202507",
"frequency": "MONTHLY"
}
],
"portfolio_composition": [
{
"isin": "LU1883308352",
"currency": "GBP",
"percentage": 50,
},
{
"isin": "LU1681046931",
"currency": "EUR",
"percentage": 50,
},
],
"target_amount": 5000,
"horizon": 60,
"current_savings": 1000,
"simulator_uuid": "aaaic:simulators:243",
}'
The above command returns JSON structured like this:
{
"success_percentage": "float",
"graphs": {
"nb_scenarios": "int",
"scenarios_smooth": [
{
"name": "string",
"data": [
{
"x": "float",
"y": "float"
}
]
}
],
"synthesis": {
"savings": {
"x": "float",
"y": "float"
},
"median": {
"x": "float",
"y": "float"
},
"lower_area": {
"x": "float",
"high": "float",
"low": "float"
},
"mid_area": {
"x": "float",
"high": "float",
"low": "float"
},
"upper_area": {
"x": "float",
"high": "float",
"low": "float"
}
},
"success_percentage": "float",
"scenarios_perc_above_cumulative_savings": "float",
"id": "string",
"scenarios": [
{
"name": "savings",
"data": [
{
"x": "float",
"y": "float"
}
],
"lineWidth": "float",
"zIndex": "float"
}
]
},
"statistics": {
"mar_ratio": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"sharp_ratio": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"annualized_return": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"max_drawdown": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"annualized_volatility": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
}
},
"scenarios_table": {
"capital_distribution_at_horizon": {
"max": "float",
"min": "float",
"in_between": {
"high": "float",
"low": "float"
}
},
"capital_gain_or_loss": {
"max": "float",
"min": "float",
"in_between": {
"high": "float",
"low": "float"
}
},
"absolute_return": {
"max": "float",
"min": "float",
"in_between": {
"high": "float",
"low": "float"
}
},
"cumulative_savings": "float",
"gross_cumulative_savings": "float"
},
"uc_allocation": [
{
"series": "string",
"percentage": "float"
}
]
}
This endpoint performs a simulation for free management allocations.
HTTP Request
POST /simulator-service/simulator/free_management
Request body
The request body is a JSON object representing a simulation request.
The SimulationRequest object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| simulator_uuid | true | string | Unique identifier of the simulator to use. Provided by AAA. |
| target_amount | false | number | The amount of money the client wishes to reach at horizon. |
| horizon | true | integer | The length (in number of months) of the project’s analysis period. |
| current_savings | false | number | The money the client has on his account before the project starts. |
| start_date | true | string | The starting point in time of the simulation. Format is YYYYMM. |
| simple_deposits | false | [SimpleCashFlow] | The series of projected one-time cash contributions. |
| periodic_deposits | false | [PeriodicCashFlow] | The series of projected recurring cash contributions. |
| simple_withdrawals | false | [SimpleCashFlow] | The series of projected one-time cash withdrawals. |
| periodic_withdrawals | false | [PeriodicCashFlow] | The series of projected recurring cash withdrawals. |
| portfolio_composition | true | [WeightedAsset] | Specifies the portfolio composition (assets and corresponding weights). |
The WeightedAsset object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| isin | true | string | The ISIN code of the asset. |
| currency | true | string | The currency of the asset, identified by a trigram (e.g. “EUR”). |
| percentage | true | number | The weight the asset represent in the portfolio, as a percentage. |
The SimpleCashFlow object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| amount | true | number | The amount of the cash flow. |
| date | true | string | The date of the cash flow. Format is YYYYMM. |
The PeriodicCashFlow object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| amount | true | number | The amount of the cash flow. |
| start_date | true | string | The date to start the recurrence. Format is YYYYMM. |
| end_date | true | string | The date to end the recurrence. Format is YYYYMM. |
| frequency | true | string | Frequency of the recurrence. Can be MONTHLY/QUARTERLY/YEARLY/SEMI_ANNUALLY |
Delegated Management
curl \
--location 'https://aaaic-backend.ppd.rafa.3a-digital.fr/simulator-service/simulator/delegated_management' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <myToken>' \
--data '{
"simulation_start_date": "202008",
"simple_deposits": [
{
"amount": 5000,
"date": "202010"
}
],
"periodic_deposits": [
{
"amount": 197.2,
"start_date": "202008",
"end_date": "202507",
"frequency": "MONTHLY"
}
],
"target_amount": 5000,
"horizon": 60,
"current_savings": 1000,
"simulator_uuid": "aaaic:simulators:236",
"profile_idx": 2
}'
The above command returns JSON structured like this:
{
"success_percentage": "float",
"graphs": {
"nb_scenarios": "int",
"scenarios_smooth": [
{
"name": "string",
"data": [
{
"x": "float",
"y": "float"
}
]
}
],
"synthesis": {
"savings": {
"x": "float",
"y": "float"
},
"median": {
"x": "float",
"y": "float"
},
"lower_area": {
"x": "float",
"high": "float",
"low": "float"
},
"mid_area": {
"x": "float",
"high": "float",
"low": "float"
},
"upper_area": {
"x": "float",
"high": "float",
"low": "float"
}
},
"success_percentage": "float",
"scenarios_perc_above_cumulative_savings": "float",
"id": "string",
"scenarios": [
{
"name": "savings",
"data": [
{
"x": "float",
"y": "float"
}
],
"lineWidth": "float",
"zIndex": "float"
}
]
},
"statistics": {
"mar_ratio": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"sharp_ratio": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"annualized_return": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"max_drawdown": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"annualized_volatility": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
}
},
"scenarios_table": {
"capital_distribution_at_horizon": {
"max": "float",
"min": "float",
"in_between": {
"high": "float",
"low": "float"
}
},
"capital_gain_or_loss": {
"max": "float",
"min": "float",
"in_between": {
"high": "float",
"low": "float"
}
},
"absolute_return": {
"max": "float",
"min": "float",
"in_between": {
"high": "float",
"low": "float"
}
},
"cumulative_savings": "float",
"gross_cumulative_savings": "float"
},
"uc_allocation": [
{
"series": "string",
"percentage": "float"
}
]
}
This endpoint performs a simulation for delegated management allocations.
HTTP Request
POST /simulator-service/simulator/delegated_management
Request body
The request body is a JSON object representing a simulation request.
The SimulationRequest object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| simulator_uuid | true | string | Unique identifier of the simulator to use. Provided by AAA. |
| target_amount | false | number | The amount of money the client wishes to reach at horizon. |
| horizon | true | integer | The length (in number of months) of the project’s analysis period. |
| current_savings | false | number | The money the client has on his account before the project starts. |
| start_date | true | string | The starting point in time of the simulation. Format is YYYYMM. |
| simple_deposits | false | [SimpleCashFlow] | The series of projected one-time cash contributions. |
| periodic_deposits | false | [PeriodicCashFlow] | The series of projected recurring cash contributions. |
| simple_withdrawals | false | [SimpleCashFlow] | The series of projected one-time cash withdrawals. |
| periodic_withdrawals | false | [PeriodicCashFlow] | The series of projected recurring cash withdrawals. |
| profile_idx | true | integer | Unique identifier of the delegated profile. Provided by AAA. |
The SimpleCashFlow object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| amount | true | number | The amount of the cash flow. |
| date | true | string | The date of the cash flow. Format is YYYYMM. |
The PeriodicCashFlow object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| amount | true | number | The amount of the cash flow. |
| start_date | true | string | The date to start the recurrence. Format is YYYYMM. |
| end_date | true | string | The date to end the recurrence. Format is YYYYMM. |
| frequency | true | string | Frequency of the recurrence. Can be MONTHLY/QUARTERLY/YEARLY/SEMI_ANNUALLY |
Glidepath Management
curl \
--location 'https://aaaic-backend.ppd.rafa.3a-digital.fr/simulator-service/simulator/glidepath_management' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <myToken>' \
--data '{
"simulation_start_date": "202008",
"simple_deposits": [
{
"amount": 5000,
"date": "202010"
}
],
"periodic_deposits": [
{
"amount": 197.2,
"start_date": "202008",
"end_date": "202507",
"frequency": "MONTHLY"
}
],
"target_amount": 5000,
"horizon": 60,
"current_savings": 1000,
"simulator_uuid": "aaaic:simulators:170",
"profile_idx": 2,
"age": 35
}'
The above command returns JSON structured like this:
{
"success_percentage": "float",
"graphs": {
"nb_scenarios": "int",
"scenarios_smooth": [
{
"name": "string",
"data": [
{
"x": "float",
"y": "float"
}
]
}
],
"synthesis": {
"savings": {
"x": "float",
"y": "float"
},
"median": {
"x": "float",
"y": "float"
},
"lower_area": {
"x": "float",
"high": "float",
"low": "float"
},
"mid_area": {
"x": "float",
"high": "float",
"low": "float"
},
"upper_area": {
"x": "float",
"high": "float",
"low": "float"
}
},
"success_percentage": "float",
"scenarios_perc_above_cumulative_savings": "float",
"id": "string",
"scenarios": [
{
"name": "savings",
"data": [
{
"x": "float",
"y": "float"
}
],
"lineWidth": "float",
"zIndex": "float"
}
]
},
"statistics": {
"mar_ratio": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"sharp_ratio": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"annualized_return": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"max_drawdown": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
},
"annualized_volatility": {
"quantile_25": "float",
"quantile_2.5": "float",
"quantile_50": "float",
"quantile_75": "float",
"quantile_97.5": "float"
}
},
"scenarios_table": {
"capital_distribution_at_horizon": {
"max": "float",
"min": "float",
"in_between": {
"high": "float",
"low": "float"
}
},
"capital_gain_or_loss": {
"max": "float",
"min": "float",
"in_between": {
"high": "float",
"low": "float"
}
},
"absolute_return": {
"max": "float",
"min": "float",
"in_between": {
"high": "float",
"low": "float"
}
},
"cumulative_savings": "float",
"gross_cumulative_savings": "float"
},
"uc_allocation": [
{
"series": "string",
"percentage": "float"
}
]
}
This endpoint performs a simulation for glidepath management allocations.
HTTP Request
POST /simulator-service/simulator/glidepath_management
Request body
The request body is a JSON object representing a simulation request.
The SimulationRequest object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| simulator_uuid | true | string | Unique identifier of the simulator to use. Provided by AAA. |
| target_amount | false | number | The amount of money the client wishes to reach at horizon. |
| horizon | true | integer | The length (in number of months) of the project’s analysis period. |
| current_savings | false | number | The money the client has on his account before the project starts. |
| start_date | true | string | The starting point in time of the simulation. Format is YYYYMM. |
| simple_deposits | false | [SimpleCashFlow] | The series of projected one-time cash contributions. |
| periodic_deposits | false | [PeriodicCashFlow] | The series of projected recurring cash contributions. |
| simple_withdrawals | false | [SimpleCashFlow] | The series of projected one-time cash withdrawals. |
| periodic_withdrawals | false | [PeriodicCashFlow] | The series of projected recurring cash withdrawals. |
| profile_idx | true | integer | Unique identifier of the delegated profile. Provided by AAA. |
| age | true | integer | The age of the customer |
The SimpleCashFlow object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| amount | true | number | The amount of the cash flow. |
| date | true | string | The date of the cash flow. Format is YYYYMM. |
The PeriodicCashFlow object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| amount | true | number | The amount of the cash flow. |
| start_date | true | string | The date to start the recurrence. Format is YYYYMM. |
| end_date | true | string | The date to end the recurrence. Format is YYYYMM. |
| frequency | true | string | Frequency of the recurrence. Can be MONTHLY/QUARTERLY/YEARLY/SEMI_ANNUALLY |
Premia Module
The Premia module is an intelligent tool that supports advisors at every step of their advisory duty. Risk profile definition and saver objectives, integration of their ESG preferences, for tailored allocation recommendations through an algorithmic adequacy engine. All this allows for automatically generating a complete investment proposal, compliant and ready to share with the saver.
This endpoint allows you to create a Premia session. You authenticate with a JWT, create a session via the API, then redirect the user to Premia with the returned session hash.
Create a Premia Session
# Example 1: subscription to a new contract
curl \
--location '{BASE_BACKEND_URL}/premia/api/v1/sessions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <myToken>' \
--data '{
"recoJourneyUuid": "aaaic:reco_journeys:4",
"extProductCode": "PERZEN",
"extSessionCode": "123456",
"contactEmail": "adeline.monet@gmail.com",
"clientLastName": "Monet",
"clientFirstName": "Adeline",
"clientBirthDate": "19800101",
"coSubscriberLastName": "Jean",
"coSubscriberFirstName": "Monet",
"coSubscriberBirthDate": "19780331",
"legalPersonName": "",
"legalPersonIdentifier": "",
"legalPersonRepresentativeLastName": "",
"legalPersonRepresentativeFirstName": "",
"depositInitialEnabled": true,
"depositInitial": 5000
}'
# Example 2: contribution / redemption / change in allocation
curl \
--location '{BASE_BACKEND_URL}/premia/api/v1/sessions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <myToken>' \
--data '{
"recoJourneyUuid": "aaaic:reco_journeys:13",
"extSessionCode": "123456",
"extProductCode": "01t0N00000B9B8pQAF",
"contactEmail": "adeline.monet@gmail.com",
"clientLastName": "Monet",
"clientFirstName": "Adeline",
"clientBirthDate": "19800101",
"coSubscriberLastName": "Jean",
"coSubscriberFirstName": "Monet",
"coSubscriberBirthDate": "19780331",
"legalPersonName": "",
"legalPersonIdentifier": "",
"legalPersonRepresentativeLastName": "",
"legalPersonRepresentativeFirstName": "",
"depositInitialEnabled": false,
"clientRiskKey": "2",
"clientRiskKeyLastUpdateDate": "20250101",
"hasSustainablePreferences": true,
"minSustainableInvestments": 15,
"minTaxonomyAlignment": null,
"minCoveragePai": 0.50,
"greenhouseGasEmissions": true,
"impactOnBiodiversity": false,
"waterEmissions": true,
"hazardousWaste": false,
"controversialWeapons": false,
"monitoringOfInternationalPrinciples": false,
"respectOfInternationalPrinciples": false,
"genderPayGap": false,
"lowBoardGenderDiversity": false,
"clientEsgLastUpdateDate": "20250101",
"periodicDepositsEnabled": true,
"regularContributionsAmount": 500,
"regularContributionsFormat": "CHOSEN_FREQUENCY",
"regularContributionsFrequency": "MONTHLY",
"currentComposition": {
"compositionParts": [
{
"partWeights": [
{
"amount": 400,
"displayName": "Mirova Europe Environnement",
"extCode": "LU0914733059"
},
{
"amount": 300,
"displayName": "Afer Rendement Juin 2023",
"extCode": "FR5272AB0288"
},
{
"amount": 250,
"displayName": "SC Advenis Immo Capital",
"extCode": "P801_SCI001"
}
],
"type": "FREE_MANAGEMENT"
}
]
}
}'
The above command returns JSON structured like this:
{
"sessionHash": "abc123"
}
HTTP Request
POST /premia/api/v1/sessions
Request body
The request body is a JSON object with all the information to initiate a session on Premia. Depending on the use case, it is built differently. Examples are provided on the right to illustrate the following cases:
- subscription to a new contract
- contribution / redemption / change in allocation for an existing contract
Response
In response, the service will provide a session hash, which is required to initiate the corresponding session on Premia.
The PremiaSessionRequest object
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| recoJourneyUuid | true | string | Identifier of the Premia configuration to use. Provided by AAA. |
| extProductCode | true | string | Your product code in the partner system (e.g., PERZEN). |
| extSessionCode | true | string | Your internal reference for traceability. |
| contactEmail | false | string | Contact email for notifications. |
| clientLastName | true | string | Client last name. |
| clientFirstName | true | string | Client first name. |
| clientBirthDate | true | string | Client birth date in YYYYMMDD format. |
| coSubscriberLastName | false | string | Co-subscriber last name (if applicable). |
| coSubscriberFirstName | false | string | Co-subscriber first name (if applicable). |
| coSubscriberBirthDate | false | string | Co-subscriber birth date in YYYYMMDD format (if applicable). |
| legalPersonName | false | string | Legal entity name (for corporate subscriptions). |
| legalPersonIdentifier | false | string | Legal entity identifier (e.g., SIREN). |
| legalPersonRepresentativeLastName | false | string | Legal representative last name (for corporate subscriptions). |
| legalPersonRepresentativeFirstName | false | string | Legal representative first name (for corporate subscriptions). |
| depositInitialEnabled | false | boolean | Whether an initial deposit is enabled. |
| depositInitial | conditional | number | Initial deposit amount. Required when depositInitialEnabled is true. |
| clientRiskKey | false | string | Client risk profile key (e.g., “2”). |
| clientRiskKeyLastUpdateDate | false | string | Date of last update of the risk profile in YYYYMMDD format. |
| hasSustainablePreferences | false | boolean | Does the client have sustainable/ESG preferences? |
| minSustainableInvestments | false | number | Minimum % of sustainable investments (use “15” for 15%). |
| minTaxonomyAlignment | false | number | Minimum % taxonomy alignment (use “15” for 15%). |
| minCoveragePai | false | number | Minimum % coverage for PAIs (use “15” for 15%). |
| greenhouseGasEmissions | false | boolean | PAI Climate. |
| impactOnBiodiversity | false | boolean | PAI Biodiversity. |
| waterEmissions | false | boolean | PAI Water quality. |
| hazardousWaste | false | boolean | PAI Responsible waste management. |
| controversialWeapons | false | boolean | PAI Controversial weapons control. |
| monitoringOfInternationalPrinciples | false | boolean | PAI Monitoring of international principles. |
| respectOfInternationalPrinciples | false | boolean | PAI Respect of international principles. |
| genderPayGap | false | boolean | PAI Gender pay gap. |
| lowBoardGenderDiversity | false | boolean | PAI Low board gender diversity. |
| clientEsgLastUpdateDate | false | string | Date of last update of ESG preferences in YYYYMMDD format. |
| periodicDepositsEnabled | false | boolean | Are periodic deposits enabled? |
| regularContributionsAmount | conditional | number | Amount of the periodic contribution. Required when periodicDepositsEnabled is true. |
| regularContributionsFormat | false | string | Contribution format. Values: “CHOSEN_FREQUENCY”. |
| regularContributionsFrequency | false | string | Contribution frequency. Values: “MONTHLY”, “QUARTERLY”, “SEMIANNUALLY”, “ANNUALLY”. |
| currentComposition | false | object | Composition of the current allocation. |
| extCode | false | string | Support code. Context: inside currentComposition.compositionParts[].partWeights[]. |
| displayName | false | string | Financial asset name. Context: inside currentComposition.compositionParts[].partWeights[]. |
| amount | false | number | Market value of the line. Context: inside currentComposition.compositionParts[].partWeights[]. |
If the input is invalid or you do not have access, the API will return standard HTTP errors (400, 403, 404) with a JSON body describing the issue.
Redirect the user to Premia
Once you receive the sessionHash, redirect the user’s browser to Premia using the following URL:
{BASE_UI_URL}/premia/sessions?hash={sessionHash}
Replace {BASE_UI_URL} with the Premia host you are integrating with (staging, production, etc.).
const res = await fetch(`${BASE_BACKEND_URL}/premia/api/v1/sessions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(payload),
});
const { sessionHash } = await res.json();
window.location.href = `${BASE_UI_URL}/premia/sessions?hash=${sessionHash}`;
Resume a Premia session
Once you know the sessionHash, redirect the user’s browser to Premia using the following URL:
{BASE_UI_URL}/premia/sessions?hash={sessionHash}
Replace {BASE_UI_URL} with the Premia host you are integrating with (staging, production, etc.).
PMS Module
The PMS module lets an asset manager read its own data from the Coanda PMS: the supports of an investment pool, the performances and characteristics of a profile, and its regulatory PRIIPs (EPT) data.
All three endpoints are read only. They are open to any authenticated asset manager, each restricted to its own perimeter: the profiles it owns and the investment pools created in its own PMS.
Dates are exchanged in ISO format, YYYY-MM-DD, both in the request and in the response.
Retrieve the supports of an investment pool
curl \
--location '{BASE_BACKEND_URL}/pms/api/v1/investment_pools/aaaic:investment_pools:6/supports' \
--header 'Authorization: Bearer <myToken>'
The above command returns JSON structured like this:
{
"investmentPoolUuid": "aaaic:investment_pools:6",
"investmentPoolName": "Bassin Actions Monde",
"supportCount": 2,
"supports": [
{
"seriesUuid": "aaaic:series:13611",
"isin": "LU1234567890",
"name": "ESG Equity Europe",
"assetClassLevel1": "EQUITIES",
"assetClassLevel2": "LARGE_CAP_EQUITIES",
"geoZoneLevel1": "EUROPE",
"geoZoneLevel2": "EUROZONE",
"hedged": false,
"inHouse": true,
"inHouseMatchedKeyword": "AM INVEST"
},
{
"seriesUuid": "aaaic:series:9042",
"isin": "IE00B4L5Y983",
"name": "iShares Core MSCI World",
"assetClassLevel1": "EQUITIES",
"assetClassLevel2": null,
"geoZoneLevel1": "GLOBAL",
"geoZoneLevel2": null,
"hedged": true,
"inHouse": false,
"inHouseMatchedKeyword": null
}
]
}
This endpoint returns the buy list of an investment pool: every support it holds, with its characteristics.
HTTP Request
GET /pms/api/v1/investment_pools/{uuid}/supports
Path parameters
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| uuid | true | string | Identifier of the investment pool, i.e. aaaic:investment_pools:6. |
Response
The response is not paginated: a pool holds at most a few hundred supports. supportCount lets you
run a consistency check on your side. Supports are sorted by ISIN.
The Support object
| Parameter | Type | Description |
|---|---|---|
| seriesUuid | string | Identifier of the support. |
| isin | string | ISIN of the support. May be null for a support without an ISIN. |
| name | string | Name of the support, as displayed in your PMS. |
| assetClassLevel1 | string | Asset class, level 1. Null when the support is not qualified yet. |
| assetClassLevel2 | string | Asset class, level 2. Null when the support is not qualified yet. |
| geoZoneLevel1 | string | Geographic zone, level 1. Null when the support is not qualified yet. |
| geoZoneLevel2 | string | Geographic zone, level 2. Null when the support is not qualified yet. |
| hedged | boolean | Whether the support is currency hedged. Null when the flag is not filled in. |
| inHouse | boolean | Whether the support is one of your own funds. |
| inHouseMatchedKeyword | string | Which configured keyword matched, so you can audit false positives. Null when none matched. |
If the pool does not exist you get a 404 PMS_INVESTMENT_POOL_NOT_FOUND. If it belongs to another
asset manager you get a 403 PMS_INVESTMENT_POOL_NOT_OWNED.
Retrieve the performances and information of a profile
# Over a given window
curl \
--location '{BASE_BACKEND_URL}/pms/api/v1/profiles/performances?insurer_code=DYN-01&start_date=2024-01-01&end_date=2026-06-30' \
--header 'Authorization: Bearer <myToken>'
# Since inception, up to the current date
curl \
--location '{BASE_BACKEND_URL}/pms/api/v1/profiles/performances?insurer_code=DYN-01' \
--header 'Authorization: Bearer <myToken>'
The above command returns JSON structured like this:
{
"insurerCode": "DYN-01",
"profileName": "Profil Dynamique",
"profileUuid": "aaaic:aaa_model_portfolios:527",
"investmentPoolUuid": "aaaic:investment_pools:6",
"inceptionDate": "2019-04-01",
"startDate": "2024-01-01",
"endDate": "2026-06-30",
"performances": {
"net": [ { "date": "2024-01-02", "value": 128.4312 } ],
"gross": [ { "date": "2024-01-02", "value": 133.1120 } ],
"netCompositionDates": [ { "date": "2024-01-02", "value": 127.8801 } ],
"grossCompositionDates": [ { "date": "2024-01-02", "value": 132.5410 } ],
"netUnitLinked": null,
"grossUnitLinked": null
},
"guaranteedFunds": [
{
"seriesUuid": "aaaic:series:4221",
"isin": "FR0000000000",
"name": "Fonds Euros",
"values": [ { "date": "2024-01-02", "value": 112.4400 } ]
}
],
"volatility": 7.42,
"feeConfigurations": [
{
"configurationDate": "2024-01-01",
"annualFees": 0.80,
"feesUnitLinkedAssets": 0.8000,
"feesEtfAssets": 0.4000,
"feesGuaranteedFunds": 0.0000,
"feesEtfTransactions": 0.1000,
"feesFrequency": "MONTHLY",
"feesDeductionDay": 1,
"feesDeductionMonth": null,
"feesDeductionWeekDay": null,
"subscriptionSeriesFees": [
{ "seriesUuid": "aaaic:series:13611", "isin": "LU1234567890", "seriesFee": 0.2500 }
]
}
],
"compositions": [
{
"compositionDate": "2024-03-11",
"executionDate": "2024-03-14",
"allocations": [
{ "seriesUuid": "aaaic:series:13611", "isin": "LU1234567890", "name": "ESG Equity Europe", "weight": 33.45 },
{ "seriesUuid": "aaaic:series:4221", "isin": "FR0000000000", "name": "Fonds Euros", "weight": 66.55 }
]
}
],
"driftedComposition": {
"referenceDate": "2026-06-30",
"lastExecutionDate": "2026-05-14",
"allocations": [
{ "seriesUuid": "aaaic:series:13611", "isin": "LU1234567890", "name": "ESG Equity Europe", "weight": 33.45, "driftedWeight": 34.12 },
{ "seriesUuid": "aaaic:series:4221", "isin": "FR0000000000", "name": "Fonds Euros", "weight": 66.55, "driftedWeight": 65.88 }
]
}
}
This endpoint returns everything there is to know about one of your profiles over a period: performance curves, volatility, guaranteed funds, fee history, rebalancing history and the allocation actually held at the end of the period.
HTTP Request
GET /pms/api/v1/profiles/performances
Query parameters
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| insurer_code | true | string | The Insurer Code carried by the profile. |
| start_date | false | string | Start of the window, inclusive. Defaults to the inception date of the profile. |
| end_date | false | string | End of the window, inclusive. Defaults to the current date. |
Response
| Parameter | Type | Description |
|---|---|---|
| insurerCode | string | The Insurer Code you requested. |
| profileName | string | Name of the profile. |
| profileUuid | string | Identifier of the profile. |
| investmentPoolUuid | string | Investment pool used by the profile. |
| inceptionDate | string | Inception date of the profile, i.e. its first executed rebalancing. |
| startDate | string | Start of the window actually applied. |
| endDate | string | End of the window actually applied. |
| performances | object | The six performance curves. See below. |
| guaranteedFunds | array | One entry per guaranteed fund found anywhere in the allocation history. |
| volatility | number | Annualised volatility in %, measured on the net curve over the window. |
| feeConfigurations | array | Fee grids applicable over the window. |
| compositions | array | Rebalancings actually executed within the window. |
| driftedComposition | object | Allocation actually held at the end of the window. |
The performances object
All curves are base 100 at the inception date and are never rebased on the requested start date. They are returned exactly as computed and stored by the PMS.
| Parameter | Description |
|---|---|
| net | Performance of the profile, net of fees. Always present. |
| gross | Performance of the profile, before fees. Always present. |
| netCompositionDates | Same, computed on the dates the allocations were entered rather than executed. |
| grossCompositionDates | Same, before fees. |
| netUnitLinked | Performance of the unit-linked pocket only, excluding the guaranteed funds. |
| grossUnitLinked | Same, before fees. |
The fee configuration object
| Parameter | Type | Description |
|---|---|---|
| configurationDate | string | Date from which this grid applies. |
| annualFees | number | Management fees on all supports, per year, in %. |
| feesUnitLinkedAssets | number | Management fees on unit-linked assets excluding ETFs, per year, in %. |
| feesEtfAssets | number | Management fees on ETFs, per year, in %. |
| feesGuaranteedFunds | number | Management fees on guaranteed funds, per year, in %. |
| feesEtfTransactions | number | ETF transaction cost, in %. |
| feesFrequency | string | Deduction frequency, i.e. MONTHLY. |
| feesDeductionDay | number | Day of deduction. |
| feesDeductionMonth | number | Month of deduction, when the frequency requires it. |
| feesDeductionWeekDay | string | Week day of deduction, when the frequency requires it. |
| subscriptionSeriesFees | array | Subscription fees defined for specific supports. |
The grid already in force when the window opens is returned first, with its configurationDate
realigned on the requested start date, so that you always know which fees applied at the beginning
of the period. Grids created later inside the window follow, in chronological order.
The composition object
Only real rebalancings are returned, identified by their execution date: the allocation in force before the window is not repeated, so a window without any move yields an empty array.
| Parameter | Type | Description |
|---|---|---|
| compositionDate | string | Date the allocation was entered. |
| executionDate | string | Date the allocation took effect. |
| allocations | array | One entry per support, with its weight in %. |
The drifted composition object
Between two rebalancings, the allocation moves on its own as markets move. This block puts the weight decided at the last rebalancing next to the weight actually reached.
| Parameter | Type | Description |
|---|---|---|
| referenceDate | string | Date the drifted weights are observed at. |
| lastExecutionDate | string | Date of the rebalancing the drift is measured from. |
| allocations | array | One entry per support, with weight and driftedWeight in %. |
If no active profile carries the Insurer Code you get a 404 PMS_PROFILE_NOT_FOUND. If several do,
you get a 400 PMS_PROFILE_CODE_NOT_UNIQUE: the server never picks one arbitrarily.
Retrieve the PRIIPs (EPT) data of a profile
curl \
--location '{BASE_BACKEND_URL}/pms/api/v1/profiles/priips?insurer_code=DYN-01&start_date=2016-01-01&end_date=2026-06-30' \
--header 'Authorization: Bearer <myToken>'
The above command returns JSON structured like this:
{
"insurerCode": "DYN-01",
"profileName": "Profil Dynamique",
"profileUuid": "aaaic:aaa_model_portfolios:527",
"inceptionDate": "2019-04-01",
"startDate": "2016-01-01",
"endDate": "2026-06-30",
"annualPerformances": {
"profileNet": [
{ "year": 2020, "performance": 4.12 },
{ "year": 2021, "performance": 11.87 },
{ "year": 2022, "performance": -9.34 }
],
"benchmark": [
{ "year": 2020, "performance": 3.90 },
{ "year": 2021, "performance": 12.10 },
{ "year": 2022, "performance": -9.80 }
]
},
"eptRecords": [
{
"eptDate": "2025-12-31",
"backfillingProxy": "80% MSCI World (spliced before 2015) / 20% Bloomberg Euro Agg",
"generalPortfolioInformation": {
"00010_Portfolio_Manufacturer_Name": "AM INVEST ASSET MANAGEMENT",
"00015_Portfolio_Manufacturer_Group_Name": "AM INVEST",
"00016_Portfolio_Manufacturer_LEI": "969500XXXXXXXXXXXX34",
"00030_Portfolio_Identifying_Data": "DYN-01",
"00040_Type_Of_Identification_Code_For_The_Fund_Share_Or_Portfolio": 99,
"00050_Portfolio_Name": "Profil Dynamique",
"00060_Portfolio_Or_Share_Class_Currency": "EUR",
"00070_PRIIPs_KID_Publication_Date": "2026-01-15",
"00075_PRIIPs_KID_Web_Address": "https://www.example.com/kid/dynamique",
"00080_Portfolio_PRIIPS_Category": 2
},
"riskAssessment": {
"01010_Valuation_Frequency": 252,
"01020_Portfolio_VEV_Reference": 12.45,
"01030_IS_Flexible": false,
"01040_Flex_VEV_Historical": null,
"01050_Flex_VEV_Ref_Asset_Allocation": null,
"01060_IS_Risk_Limit_Relevant": false,
"01080_Existing_Credit_Risk": false,
"01090_SRI": 4,
"01095_IS_SRI_Adjusted": false,
"01100_MRM": 4,
"01110_CRM": 1,
"01120_Recommended_Holding_Period": 8,
"01140_Liquidity_Risk": "M"
},
"performanceScenarios": {
"02010_Portfolio_Return_Unfavourable_Scenario_1_Year": -18.42,
"02020_Portfolio_Return_Unfavourable_Scenario_Half_RHP": -4.11,
"02030_Portfolio_Return_Unfavourable_Scenario_RHP_Or_First_Call_Date": -1.22,
"02040_Portfolio_Return_Moderate_Scenario_1_Year": 3.95,
"02100_Portfolio_Return_Stress_Scenario_1_Year": -32.10,
"02130_Portfolio_Number_Of_Observed_Return_M0": 2520,
"02220_Reference_Invested_Amount": 10000
},
"costs": {
"03010_One_Off_Cost_Portfolio_Entry_Cost": 0.00,
"03050_One_Off_Costs_Portfolio_Sliding_Exit_Cost_Indicator": false,
"03060_Ongoing_Costs_Management_Fees_And_Other_Administrative_Or_Operating_Costs": 1.72,
"03080_Ongoing_Costs_Portfolio_Transaction_Costs": 0.11,
"03095_Incidental_Costs_Portfolio_Performance_Fees": 0.00,
"feesDelegatedPortfolioManagementUnitLinked": 0.80,
"feesDelegatedPortfolioManagementEtf": 0.40,
"feesDelegatedPortfolioManagementGuaranteedFunds": 0.00
},
"displayedCostsAndRiy": {
"07010_Total_Cost_1_Year_Or_First_Call": 183.00,
"07020_RIY_1_Year_Or_First_Call": 1.83,
"07030_Total_Cost_Half_RHP": 780.00,
"07040_RIY_Half_RHP": 1.81,
"07050_Total_Cost_RHP": 1620.00,
"07060_RIY_RHP": 1.80
}
}
]
}
This endpoint returns the regulatory data of one of your profiles: its calendar year performances and every EPT recorded over the period, split into the five standard blocks.
HTTP Request
GET /pms/api/v1/profiles/priips
Query parameters
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| insurer_code | true | string | The Insurer Code carried by the profile. |
| start_date | false | string | Start of the window, inclusive. Defaults to the inception date of the profile. |
| end_date | false | string | End of the window, inclusive. Defaults to the current date. |
Response
| Parameter | Type | Description |
|---|---|---|
| insurerCode | string | The Insurer Code you requested. |
| profileName | string | Name of the profile. |
| profileUuid | string | Identifier of the profile. |
| inceptionDate | string | Inception date of the profile. |
| startDate | string | Start of the window actually applied to the EPT records. |
| endDate | string | End of the window actually applied to the EPT records. |
| annualPerformances | object | Calendar year performances of the profile and of its benchmark. |
| eptRecords | array | One entry per EPT whose date falls in the window, in chronological order. |
The annualPerformances object
| Parameter | Type | Description |
|---|---|---|
| profileNet | array | Calendar year performances of the profile, net of fees, as { year, performance } in %. |
| benchmark | array | Same on the benchmark. Null when no benchmark is configured on the profile. |
The EPT record object
| Parameter | Type | Description |
|---|---|---|
| eptDate | string | Date of the EPT. |
| backfillingProxy | string | Free text describing the composite index used to extend the profile history when it is shorter than the depth PRIIPs requires. |
| generalPortfolioInformation | object | Who manufactures the profile, under which name and currency, and where its KID can be found. |
| riskAssessment | object | Regulatory risk level, including the SRI graded from 1 to 7. |
| performanceScenarios | object | The four regulatory market scenarios and the statistics they derive from. |
| costs | object | Everything the saver pays, on entry, during the life of the contract and on exit. |
| displayedCostsAndRiy | object | Costs as printed on the KID, in currency and as a reduction in yield. |
If no active profile carries the Insurer Code you get a 404 PMS_PROFILE_NOT_FOUND. If several do,
you get a 400 PMS_PROFILE_CODE_NOT_UNIQUE.
Errors
The Coanda API uses the following error codes:
4xx
| Error Code | Meaning |
|---|---|
| 401 | Unauthorized – Token is invalid. |
| 403 | Forbidden – Credentials are correct but permissions are not. |
| 404 | Not Found – The specified endpoint does not exist. |
| 405 | Method Not Allowed – You tried to access a endpoint with an invalid method. |
| 422 | Bad Request – Your request is invalid. |
| 429 | Too Many Requests – You’re sending too many requests in a small interval. Slow down! |
5xx
| Error Code | Meaning |
|---|---|
| 500 | Internal Server Error – We had a problem with our server. Try again later. |
| 503 | Service Unavailable – We’re temporarily offline for maintenance. Please try again later. |
PMS Module
Endpoints of the PMS Module return a business code in the code field of the error body, on top of
the HTTP status.
| Code | Status | Meaning |
|---|---|---|
| PMS_PROFILE_NOT_FOUND | 404 | No active profile carries this Insurer Code within your perimeter. |
| PMS_PROFILE_CODE_NOT_UNIQUE | 400 | Several active profiles carry this Insurer Code: the server never picks one arbitrarily. |
| PMS_INVESTMENT_POOL_NOT_FOUND | 404 | No such investment pool. |
| PMS_INVESTMENT_POOL_NOT_OWNED | 403 | The investment pool belongs to another asset manager. |
| PMS_INVALID_DATE_RANGE | 400 | The end date is earlier than the start date. An absent end date defaults to the current date. |
