NAV

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 myToken with 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

ParameterDescription
usernameYour username/clientId. Must be sent url_encoded.
passwordYour 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)

ParameterDescription
grant_typeMust be set to client_credentials.
client_idYour client identifier.
client_secretYour client secret.

Response

FieldDescription
access_tokenThe generated JWT token.
token_typeThe 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

ParameterMandatoryTypeDescription
simulator_uuidtruestringUnique identifier of the simulator to use. Provided by AAA.
target_amountfalsenumberThe amount of money the client wishes to reach at horizon.
horizontrueintegerThe length (in number of months) of the project’s analysis period.
current_savingsfalsenumberThe money the client has on his account before the project starts.
start_datetruestringThe starting point in time of the simulation. Format is YYYYMM.
simple_depositsfalse[SimpleCashFlow]The series of projected one-time cash contributions.
periodic_depositsfalse[PeriodicCashFlow]The series of projected recurring cash contributions.
simple_withdrawalsfalse[SimpleCashFlow]The series of projected one-time cash withdrawals.
periodic_withdrawalsfalse[PeriodicCashFlow]The series of projected recurring cash withdrawals.
portfolio_compositiontrue[WeightedAsset]Specifies the portfolio composition (assets and corresponding weights).

The WeightedAsset object

ParameterMandatoryTypeDescription
isintruestringThe ISIN code of the asset.
currencytruestringThe currency of the asset, identified by a trigram (e.g. “EUR”).
percentagetruenumberThe weight the asset represent in the portfolio, as a percentage.

The SimpleCashFlow object

ParameterMandatoryTypeDescription
amounttruenumberThe amount of the cash flow.
datetruestringThe date of the cash flow. Format is YYYYMM.

The PeriodicCashFlow object

ParameterMandatoryTypeDescription
amounttruenumberThe amount of the cash flow.
start_datetruestringThe date to start the recurrence. Format is YYYYMM.
end_datetruestringThe date to end the recurrence. Format is YYYYMM.
frequencytruestringFrequency 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

ParameterMandatoryTypeDescription
simulator_uuidtruestringUnique identifier of the simulator to use. Provided by AAA.
target_amountfalsenumberThe amount of money the client wishes to reach at horizon.
horizontrueintegerThe length (in number of months) of the project’s analysis period.
current_savingsfalsenumberThe money the client has on his account before the project starts.
start_datetruestringThe starting point in time of the simulation. Format is YYYYMM.
simple_depositsfalse[SimpleCashFlow]The series of projected one-time cash contributions.
periodic_depositsfalse[PeriodicCashFlow]The series of projected recurring cash contributions.
simple_withdrawalsfalse[SimpleCashFlow]The series of projected one-time cash withdrawals.
periodic_withdrawalsfalse[PeriodicCashFlow]The series of projected recurring cash withdrawals.
profile_idxtrueintegerUnique identifier of the delegated profile. Provided by AAA.

The SimpleCashFlow object

ParameterMandatoryTypeDescription
amounttruenumberThe amount of the cash flow.
datetruestringThe date of the cash flow. Format is YYYYMM.

The PeriodicCashFlow object

ParameterMandatoryTypeDescription
amounttruenumberThe amount of the cash flow.
start_datetruestringThe date to start the recurrence. Format is YYYYMM.
end_datetruestringThe date to end the recurrence. Format is YYYYMM.
frequencytruestringFrequency 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

ParameterMandatoryTypeDescription
simulator_uuidtruestringUnique identifier of the simulator to use. Provided by AAA.
target_amountfalsenumberThe amount of money the client wishes to reach at horizon.
horizontrueintegerThe length (in number of months) of the project’s analysis period.
current_savingsfalsenumberThe money the client has on his account before the project starts.
start_datetruestringThe starting point in time of the simulation. Format is YYYYMM.
simple_depositsfalse[SimpleCashFlow]The series of projected one-time cash contributions.
periodic_depositsfalse[PeriodicCashFlow]The series of projected recurring cash contributions.
simple_withdrawalsfalse[SimpleCashFlow]The series of projected one-time cash withdrawals.
periodic_withdrawalsfalse[PeriodicCashFlow]The series of projected recurring cash withdrawals.
profile_idxtrueintegerUnique identifier of the delegated profile. Provided by AAA.
agetrueintegerThe age of the customer

The SimpleCashFlow object

ParameterMandatoryTypeDescription
amounttruenumberThe amount of the cash flow.
datetruestringThe date of the cash flow. Format is YYYYMM.

The PeriodicCashFlow object

ParameterMandatoryTypeDescription
amounttruenumberThe amount of the cash flow.
start_datetruestringThe date to start the recurrence. Format is YYYYMM.
end_datetruestringThe date to end the recurrence. Format is YYYYMM.
frequencytruestringFrequency 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:

Response

In response, the service will provide a session hash, which is required to initiate the corresponding session on Premia.

The PremiaSessionRequest object

ParameterMandatoryTypeDescription
recoJourneyUuidtruestringIdentifier of the Premia configuration to use. Provided by AAA.
extProductCodetruestringYour product code in the partner system (e.g., PERZEN).
extSessionCodetruestringYour internal reference for traceability.
contactEmailfalsestringContact email for notifications.
clientLastNametruestringClient last name.
clientFirstNametruestringClient first name.
clientBirthDatetruestringClient birth date in YYYYMMDD format.
coSubscriberLastNamefalsestringCo-subscriber last name (if applicable).
coSubscriberFirstNamefalsestringCo-subscriber first name (if applicable).
coSubscriberBirthDatefalsestringCo-subscriber birth date in YYYYMMDD format (if applicable).
legalPersonNamefalsestringLegal entity name (for corporate subscriptions).
legalPersonIdentifierfalsestringLegal entity identifier (e.g., SIREN).
legalPersonRepresentativeLastNamefalsestringLegal representative last name (for corporate subscriptions).
legalPersonRepresentativeFirstNamefalsestringLegal representative first name (for corporate subscriptions).
depositInitialEnabledfalsebooleanWhether an initial deposit is enabled.
depositInitialconditionalnumberInitial deposit amount. Required when depositInitialEnabled is true.
clientRiskKeyfalsestringClient risk profile key (e.g., “2”).
clientRiskKeyLastUpdateDatefalsestringDate of last update of the risk profile in YYYYMMDD format.
hasSustainablePreferencesfalsebooleanDoes the client have sustainable/ESG preferences?
minSustainableInvestmentsfalsenumberMinimum % of sustainable investments (use “15” for 15%).
minTaxonomyAlignmentfalsenumberMinimum % taxonomy alignment (use “15” for 15%).
minCoveragePaifalsenumberMinimum % coverage for PAIs (use “15” for 15%).
greenhouseGasEmissionsfalsebooleanPAI Climate.
impactOnBiodiversityfalsebooleanPAI Biodiversity.
waterEmissionsfalsebooleanPAI Water quality.
hazardousWastefalsebooleanPAI Responsible waste management.
controversialWeaponsfalsebooleanPAI Controversial weapons control.
monitoringOfInternationalPrinciplesfalsebooleanPAI Monitoring of international principles.
respectOfInternationalPrinciplesfalsebooleanPAI Respect of international principles.
genderPayGapfalsebooleanPAI Gender pay gap.
lowBoardGenderDiversityfalsebooleanPAI Low board gender diversity.
clientEsgLastUpdateDatefalsestringDate of last update of ESG preferences in YYYYMMDD format.
periodicDepositsEnabledfalsebooleanAre periodic deposits enabled?
regularContributionsAmountconditionalnumberAmount of the periodic contribution. Required when periodicDepositsEnabled is true.
regularContributionsFormatfalsestringContribution format. Values: “CHOSEN_FREQUENCY”.
regularContributionsFrequencyfalsestringContribution frequency. Values: “MONTHLY”, “QUARTERLY”, “SEMIANNUALLY”, “ANNUALLY”.
currentCompositionfalseobjectComposition of the current allocation.
extCodefalsestringSupport code. Context: inside currentComposition.compositionParts[].partWeights[].
displayNamefalsestringFinancial asset name. Context: inside currentComposition.compositionParts[].partWeights[].
amountfalsenumberMarket 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

ParameterMandatoryTypeDescription
uuidtruestringIdentifier 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

ParameterTypeDescription
seriesUuidstringIdentifier of the support.
isinstringISIN of the support. May be null for a support without an ISIN.
namestringName of the support, as displayed in your PMS.
assetClassLevel1stringAsset class, level 1. Null when the support is not qualified yet.
assetClassLevel2stringAsset class, level 2. Null when the support is not qualified yet.
geoZoneLevel1stringGeographic zone, level 1. Null when the support is not qualified yet.
geoZoneLevel2stringGeographic zone, level 2. Null when the support is not qualified yet.
hedgedbooleanWhether the support is currency hedged. Null when the flag is not filled in.
inHousebooleanWhether the support is one of your own funds.
inHouseMatchedKeywordstringWhich 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

ParameterMandatoryTypeDescription
insurer_codetruestringThe Insurer Code carried by the profile.
start_datefalsestringStart of the window, inclusive. Defaults to the inception date of the profile.
end_datefalsestringEnd of the window, inclusive. Defaults to the current date.

Response

ParameterTypeDescription
insurerCodestringThe Insurer Code you requested.
profileNamestringName of the profile.
profileUuidstringIdentifier of the profile.
investmentPoolUuidstringInvestment pool used by the profile.
inceptionDatestringInception date of the profile, i.e. its first executed rebalancing.
startDatestringStart of the window actually applied.
endDatestringEnd of the window actually applied.
performancesobjectThe six performance curves. See below.
guaranteedFundsarrayOne entry per guaranteed fund found anywhere in the allocation history.
volatilitynumberAnnualised volatility in %, measured on the net curve over the window.
feeConfigurationsarrayFee grids applicable over the window.
compositionsarrayRebalancings actually executed within the window.
driftedCompositionobjectAllocation 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.

ParameterDescription
netPerformance of the profile, net of fees. Always present.
grossPerformance of the profile, before fees. Always present.
netCompositionDatesSame, computed on the dates the allocations were entered rather than executed.
grossCompositionDatesSame, before fees.
netUnitLinkedPerformance of the unit-linked pocket only, excluding the guaranteed funds.
grossUnitLinkedSame, before fees.

The fee configuration object

ParameterTypeDescription
configurationDatestringDate from which this grid applies.
annualFeesnumberManagement fees on all supports, per year, in %.
feesUnitLinkedAssetsnumberManagement fees on unit-linked assets excluding ETFs, per year, in %.
feesEtfAssetsnumberManagement fees on ETFs, per year, in %.
feesGuaranteedFundsnumberManagement fees on guaranteed funds, per year, in %.
feesEtfTransactionsnumberETF transaction cost, in %.
feesFrequencystringDeduction frequency, i.e. MONTHLY.
feesDeductionDaynumberDay of deduction.
feesDeductionMonthnumberMonth of deduction, when the frequency requires it.
feesDeductionWeekDaystringWeek day of deduction, when the frequency requires it.
subscriptionSeriesFeesarraySubscription 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.

ParameterTypeDescription
compositionDatestringDate the allocation was entered.
executionDatestringDate the allocation took effect.
allocationsarrayOne 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.

ParameterTypeDescription
referenceDatestringDate the drifted weights are observed at.
lastExecutionDatestringDate of the rebalancing the drift is measured from.
allocationsarrayOne 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

ParameterMandatoryTypeDescription
insurer_codetruestringThe Insurer Code carried by the profile.
start_datefalsestringStart of the window, inclusive. Defaults to the inception date of the profile.
end_datefalsestringEnd of the window, inclusive. Defaults to the current date.

Response

ParameterTypeDescription
insurerCodestringThe Insurer Code you requested.
profileNamestringName of the profile.
profileUuidstringIdentifier of the profile.
inceptionDatestringInception date of the profile.
startDatestringStart of the window actually applied to the EPT records.
endDatestringEnd of the window actually applied to the EPT records.
annualPerformancesobjectCalendar year performances of the profile and of its benchmark.
eptRecordsarrayOne entry per EPT whose date falls in the window, in chronological order.

The annualPerformances object

ParameterTypeDescription
profileNetarrayCalendar year performances of the profile, net of fees, as { year, performance } in %.
benchmarkarraySame on the benchmark. Null when no benchmark is configured on the profile.

The EPT record object

ParameterTypeDescription
eptDatestringDate of the EPT.
backfillingProxystringFree text describing the composite index used to extend the profile history when it is shorter than the depth PRIIPs requires.
generalPortfolioInformationobjectWho manufactures the profile, under which name and currency, and where its KID can be found.
riskAssessmentobjectRegulatory risk level, including the SRI graded from 1 to 7.
performanceScenariosobjectThe four regulatory market scenarios and the statistics they derive from.
costsobjectEverything the saver pays, on entry, during the life of the contract and on exit.
displayedCostsAndRiyobjectCosts 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 CodeMeaning
401Unauthorized – Token is invalid.
403Forbidden – Credentials are correct but permissions are not.
404Not Found – The specified endpoint does not exist.
405Method Not Allowed – You tried to access a endpoint with an invalid method.
422Bad Request – Your request is invalid.
429Too Many Requests – You’re sending too many requests in a small interval. Slow down!

5xx

Error CodeMeaning
500Internal Server Error – We had a problem with our server. Try again later.
503Service 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.

CodeStatusMeaning
PMS_PROFILE_NOT_FOUND404No active profile carries this Insurer Code within your perimeter.
PMS_PROFILE_CODE_NOT_UNIQUE400Several active profiles carry this Insurer Code: the server never picks one arbitrarily.
PMS_INVESTMENT_POOL_NOT_FOUND404No such investment pool.
PMS_INVESTMENT_POOL_NOT_OWNED403The investment pool belongs to another asset manager.
PMS_INVALID_DATE_RANGE400The end date is earlier than the start date. An absent end date defaults to the current date.