Products, Contracts & CostPlans

Products

As a giroprovider you might want to offer your clients multiple options when it comes to opening an account. These options could be:

  • Individual holder account: a “regular” account for an individual person
  • Shared account: a “regular” account for two people who, for example, are married
  • Pension account: an account that is used for saving up an individual’s pension. Withdrawals might be disabled until the individual reaches pension-age
  • Child account: an account for a guardian and a child where the guardian loses access rights whilst the child gains them when the child becomes 18 years of age
  • Corporate account: an account for a company or foundation

These types of accounts aren’t presets within GiroPro, but rather collections of rules and permissions defined by the giroprovider in something called a Product.

Products are created by the giroprovider in the backoffice. Therefore we only need to know how to retrieve them.

Retrieving Products

To retrieve the Products GiroPro offers two endpoints. Both endpoints return one or more ProductAggregatedItems which look like this:

{
  "return_type": "ProductAggregatedItem",
  "id": "daa7484b-f43b-4cc3-8d03-7332b92e61d2",
  "labelId": "357a12a1-a12a-12ab-a123-a12a1a1ab357",
  "productName": "Pension product",
  "description": "Product for pension-investing",
  "url": "",
  "defaultCurrency": "EUR",
  "minDepositAmount": 20.0, // minimum gross value-amount for buy-type Orders
  "maxDepositAmount": 249999.99, // maximum gross value-amount for buy-type Orders
  "minCollectionAmount": 1.0, // minimum gross value-amount for periodical buy-type Orders
  "maxCollectionAmount": 10000.0, // maximum gross value-amount for periodical buy-type Orders
  "pledgeAllowed": false,
  "costPlanId": "8ccd97a0-4dde-4c35-b1ce-13b67a798afd", // ID of applicable CostPlan
  "costPlanItem": {
  	// applicable CostPlan
  }, 
  "overridingCostPlans": [ // possible overriding CostPlans for certain assets
    {
      "assetId": "5da7c92d-0930-42fb-adf3-c1a5b0f3d0ce",
      "costPlanId": "c6bf9a81-3069-4f7b-920c-0a02c7ced053"
    }
  ],
  "listAllowedCurrencies": [
    "EUR"
  ],
  "listAllowedCountries": [], // whitelist of nationalities that can use this Product
  "listNotAllowedNationalities": [], // blacklist of nationalities that can't use this Product
  "listOfAssetsAllowed": [
    // list of AssetIds the investor can invest in with this Product
  ],
  "listOfAssetsAllowedItems": [
    // list of Assets the investor can invest in with this Product
  ],
  "creationDate": "2000-01-01T00:00:00Z",
  "validFromDate": "2000-01-01T00:00:00Z",
  "directDebitDeadline": 4,
  "dividend": true,
  "dividendOption": "ReInvest",
  "directDebitRecurrence": {
    "rRuleString": "RRULE:FREQ=MONTHLY;BYMONTHDAY=10",
    "startDate": "2024-10-06T00:00:00Z",
    "nextDate": "2025-06-10T00:00:00Z"
  },
  "versionState": "None",
  "periodicalBuy": true, // whether periodical buy-Orders are allowed with this Product
  "periodicalSell": false, // whether periodical sell-Orders are allowed with this Product
  "directSwitchAllowed": true, // whether direct switch-Orders are allowed with this Product
  "indirectSwitchAllowed": true, // whether indirect switch-Orders are allowed with Product Product
  "internalSwitchAllowed": true, // whether internal switch-Orders are allowed with this Product
  "jointOwnershipOfInvestorAccountAllowed": false, // whether multiple investors are allowed with this Product
  "legalEntityAllowed": false, // whether companies can use this Product
  "predefinedAssetMixAllowed": false, // whether predefined AssetMixes are allowed with this Product
  "selfDefinedAssetMixAllowed": true, // whether investor-defined AssetMixes are allowed with this Product
  "rebalanceAllowed": true, // whether rebalancing the portfolio is allowed with this Product
  "proRataAllowed": true,
  "rebalanceBuy": false,
  "rebalanceSell": false,
  "tradeSafetyMargin": 0.8,
  "sellAllowedByInvestor": true,
  "buyAllowedByInvestor": true,
  "switchAllowedByInvestor": true,
  "fiscalPolicy": "BOX3",
  "creditLimit": 0.0,
  "periodicalSellMinAmount": 1.0,
  "periodicalSellMaxAmount": 10000.0,
  "dwacDepositAllowed": true,
  "dwacWithdrawAllowed": true,
  "periodicalBuyRefundProcessingDays": 0,
  "allocateOnNegativeCash": false,
  "assetMixBuyAllowed": true,
  "assetMixSellAllowed": false
}

GET /ProductGetById/

The /ProductGetById/ endpoint returns a single ProductAggregatedItem for the provided labelId and ProductId.

const url = 'https://api.dev.giropro.pengine.com/PENGINE/Aggregator/AssetAggregator/ProductGetById/<labelId>/<productId>';
const options = {
  method: 'GET', 
  headers: {
    accept: 'application/json',
    authorization: 'bearer <token>'
  }
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));

Calling this endpoint returns a PengineResult containing a single ProductAggregatedItem.

GET /Products/

The /Products/ endpoint returns all ProductAggregatedItems that match the provided labelId and query parameters:

const url = 'https://api.dev.giropro.pengine.com/PENGINE/Aggregator/AssetAggregator/Products/<labelId>?skip=0&limit=5';
const options = {
  method: 'GET', 
  headers: {
    accept: 'application/json',
    authorization: 'bearer <token>'
  }
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));

This call returns a PengineResult containing a maximum of 5 ProductAggregatedItems that match the provided query.

When to use

The /ProductGetById/ endpoint is best used to get the details of the relevant ProductAggregatedItem.

The /Products/ endpoint is used to retrieve all ProductAggregatedItems so the investor can compare their definitions to find the best fit for their use case.


Contracts

To tie the Products to the individual InvestorAccounts, GiroPro uses Contracts. A Contract defines the agreement between the investor and the giroprovider and thereby sets rules and permissions on an InvestorAccount.

Contracts are created by the giroprovider in the backoffice. Therefore we only need to know how to retrieve them.

Retrieving Contracts

To retrieve the Contracts GiroPro offers two endpoints. Both endpoints return one or more ContractAggregatedItems which look like this:

{
  "return_type": "ContractAggregatedItem",
  "id": "4fe992b8-d994-4024-959a-8e8421210a86",
  "labelId": "357a12a1-a12a-12ab-a123-a12a1a1ab357",
  "investorAccountId": "4563a12a1-a12a-12ab-a123-a12a1a1ab456", // ID of the InvestoAccount this Contract applies to
  "productId": "daa7484b-f43b-4cc3-8d03-7332b92e61d2", // ID of Product that is relevant for this Contract
  "productItem": {
    // the relevant Product
  },
  "costPlanId": "8ccd97a0-4dde-4c35-b1ce-13b67a798afd", // ID of the applicable CostPlan
  "costPlanItem": {
    // the applicable CostPlan
  },
  "creationDate": "2005-07-01T00:00:00Z",
  "validFromDate": "2005-07-01T00:00:00Z",
  "excludedAssetIds": [
    "be5f5770-2301-4296-9230-69c88ac6a637"
  ]
}

GET /ContractGetById/

The /ContractGetById/ endpoint returns a single ContractAggregatedItem for the provided labelId and ContractId.

const url = 'https://api.dev.giropro.pengine.com/PENGINE/Aggregator/AssetAggregator/ContractGetById/<labelId>/<contractId>';
const options = {
  method: 'GET', 
  headers: {
    accept: 'application/json',
    authorization: 'bearer <token>'
  }
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));

Calling this endpoint returns a PengineResult containing a single ContractAggregatedItem.

GET /Contracts/

The /Contracts/ endpoint returns all ContractAggregatedItems that match the provided labelId and query parameters:

const url = 'https://api.dev.giropro.pengine.com/PENGINE/Aggregator/AssetAggregator/Contracts/<labelId>?skip=0&limit=5&query[0].column=investorId&query[0].value=<investorId>&query[0].comparisonType=exact';
const options = {
  method: 'GET', 
  headers: {
    accept: 'application/json',
    authorization: 'bearer <token>'
  }
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));

This call returns a PengineResult containing a maximum of 5 ContractAggregatedItems that match the provided query.

When to use

The /ContractGetById/ endpoint is best used to get the details of the relevant ContractAggregatedItem.

The /Contracts/ endpoint is used to retrieve all ContractAggregatedItems for a specific User or Investor.




CostPlans

To cover operating costs, brokerage fees and to make money we charge costs to the investor. To be able to calculate these Costs and to convey to the investor what these costs are, GiroPro uses something called CostPlans. A CostPlan is made up of CostComponents.

Contracts are created by the giroprovider in the backoffice. Therefore we only need to know how to retrieve them.

CostComponent

A CostComponent is a description of a cost that is charged to the investor. This can be a (periodical) percentage or a flat-fee. CostComponents are described in the CostComponentItem:

{
  "activeCostComponent": "Percentage" // CostComponent type, options are: Percentage, FixedAmount, MinimumAmount, MaximumAmount, SlidingScale, Manual
  "type": "Buy", // what orderType this component applies to, options are: Sell, Buy, Switch, SwitchSell, SwitchBuy, PeriodicalBuy, PeriodicalSell, Refund, ReInvestment
  "code": "B", // code for internal usage to quickly identify the type, pattern: ^[A-Z]{1,3}$
  "percentage": 0.25, // in this case the percentage applicable for this order, this value is in actual percentage value, so 0.25% in this case.
  "slidingScale": [], // the optional applicable sliding scale
}

Retrieving CostPlans

A CostPlan is a collection of CostComponents. We use the CostPlan to convey to the investor what expenses are connected to Orders before placing them. The execution of theses CostPlans are performed automatically by GiroPro. CostPlans are described in the CostPlanAggregatedItem

{
  "return_type": "CostPlanAggregatedItem",
  "id": "5433fb25-768a-4c2c-a684-3eb575a02be8",
  "name": "Standaard",
  "labelId": "357a12a1-a12a-12ab-a123-a12a1a1ab357",
  "plan": [
    // list of all CostComponents relevant for this CostPlan
  ],
  "validFrom": "2000-01-01T00:00:00Z",
  "versionState": "None"
}

GET /CostPlanGetById/

The /CostPlanGetById/ endpoint returns a single CostPlanAggregatedItem for the provided labelId and costPlanId.

const url = 'https://api.dev.giropro.pengine.com/PENGINE/Aggregator/AssetAggregator/CostPlanGetById/<labelId>/<costPlanId>';
const options = {
  method: 'GET', 
  headers: {
    accept: 'application/json',
    authorization: 'bearer <token>'
  }
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));

Calling this endpoint returns a PengineResult containing a single CostPlanAggregatedItem.

GET /CostPlans/

The /CostPlans/ endpoint returns all CostPlanAggregatedItems that match the provided labelId and query parameters:

const url = 'https://api.dev.giropro.pengine.com/PENGINE/Aggregator/AssetAggregator/CostPlans/<labelId>?skip=0&limit=5';
const options = {
  method: 'GET', 
  headers: {
    accept: 'application/json',
    authorization: 'bearer <token>'
  }
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));

This call returns a PengineResult containing a maximum of 5 CostPlanAggregatedItems that match the provided query.

When to use

The /CostPlanGetById/ endpoint is best used to get the details of the relevant CostPlanAggregatedItem.

The /CostPlans/ endpoint is used to retrieve all CostPlanAggregatedItems so the investor can compare their definitions to find the best fit for their use case.


Back to top

© 2026 Pengine.