# Price sources

Source: https://docs.settlemint.com/docs/console/organisation-settings/price-sources
Connect a provider's prices to token price feeds by ISIN, see the checks a price passes before it is published, decide held prices and act on a stale feed.

A price source connects one price provider, such as a custodian's end-of-day file, a market-data vendor or a trading counterparty, to the price feeds of your tokens. The platform fetches the provider's prices, checks each one, and publishes the prices that pass to the token's price feed.

The organisation's operations signer, the custody account the platform uses to sign on the organisation's behalf, signs each published price. Use this page to add a source, map its instruments, decide held prices and act when a feed goes stale.

Use [Token pricing](https://docs.settlemint.com/docs/console/asset-management/manage/token-pricing) to set a price by hand, and [Data feeds](https://docs.settlemint.com/docs/console/organisation-settings/data-feeds) for feed registration and staleness windows.

A source works with ISINs. An ISIN, short for International Securities Identification Number, is the 12-character code that identifies a security. The provider names each price by ISIN, and you map each ISIN to the token whose feed receives the price. A token that has no price feed gets one when you map it, quoted in the mapping's currency.

![Sources tab of Data feeds with the list of price sources](https://docs.settlemint.com/docs/screenshots/console-data-feeds-price-sources.light.en.webp)

[Screenshot] The "Sources" tab lists each source with its protocol, the number of mapped instruments, the time of its last delivery and its status, and an "Add source" button.

## Before you start [#before-you-start]

- You need the "Feeds manager" role to see the "Sources" tab, add a source and manage it. The system needs its feeds directory installed.
- You need your PIN for the steps that save a credential, save settings, trust a host key, map an instrument, activate or resume a source, remove a credential, and approve or reject a held price.
- To decide a held price you need the "Feeds manager" role or the "Governance" role on the token, and you must not be in the group the price excludes.
- Turn the **Prices** approval on in [General](https://docs.settlemint.com/docs/console/organisation-settings/general#approvals) before you activate a source if held prices must be reviewed. [Held prices and the second approver](#held-prices-and-the-second-approver) explains the rule.
- Have the provider's connection details and credential ready. A platform operator prepares the deployment first: the endpoint allow list, a fixed outbound address for Bloomberg and the stale-feed alert, described in [Price source prerequisites](https://docs.settlemint.com/docs/deployment/price-source-prerequisites).

## Steps [#steps]

### Add the source [#add-the-source]

On the "Sources" tab, select **Add source**. It opens the "Add source" page, which reads "Connect a vendor price source. It is saved inactive."

Under **How the source delivers prices**, choose one method:

- **File** for a file on an SFTP server. A file source then asks for its "File format", "CSV" or "ISO 20022 reda.001".
- **FIX** for a FIX market data session.
- **REST** for a vendor request. A vendor request then asks for its "Vendor", "Bloomberg Data License" or "LSEG DataScope Select".

The fields that follow match that choice, in the sections "Source", "Protocol", "Prices", "Credential", "Publishing" and "Timing". [Connection fields](#connection-fields) lists them.

A source keeps its delivery method for its whole life, because its credential and connection fields follow from it. To change the method later, add a new source and map the ISINs again.

These values decide when a price reaches the feed:

- **Publish after a move of (bps)** sets how far a price must move from the last published price before it is published. A basis point, bps, is one hundredth of a percent.
- **Or at least every (hours)** is the heartbeat: a newer price is published after this interval even when it moved less than the threshold. A heartbeat never re-stamps an old price. Leave it empty for no heartbeat.
- **Hold above (percent)** sets how far a price may move before it is held.
- **Expected every (hours)** is how often the provider delivers.
- **Expected lag (hours)** is how long after its observed time a price normally arrives.
- **Stale after (hours)** is the age at which a price counts as stale. It applies only when the feed's staleness window, its own or the global default on Data feeds, is set to never expire.

The heartbeat plus the expected interval plus the expected lag must be shorter than the staleness bound. The bound is the feed's staleness window, its own or the global default, when that window is finite, else "Stale after". Otherwise the form refuses the source with "The heartbeat plus the expected interval plus the expected lag comes to `<total>`, which is not shorter than the `<bound>` staleness bound. Shorten one of them or raise Stale after." The form fills `<total>` and `<bound>` with the two durations. The rule keeps the feed from going stale between two deliveries.

The form refuses a host that is a loopback, private or metadata address, and a FIX session without TLS outside the deployment's endpoint allow list. Use the provider's public host name.

Enter the credential and select **Add source**. A "Confirm the credential" dialog asks for your PIN. The credential is stored in the platform secret store and is never shown again. The source is saved as "Draft".

If the source was saved but the credential was not, the page says "The source was added without its credential". Enter the credential again and select **Save credential**, or select "Open source" and add it there.

### Test the connection [#test-the-connection]

Open the source and select the "Connection" tab. **Test connection** opens a session with the source and checks that it answers. It fetches and publishes nothing. The result says "The source answered" or "The connection failed" with the reason, and names the egress IP address the provider saw, so you can give it to the provider to allow.

For an SFTP source, a host key the server offers that is not trusted yet shows its fingerprint. Compare it with the fingerprint your provider published, select **Trust this host key** only if the two match, and confirm with your PIN.

### Map the instruments [#map-the-instruments]

Open the "Instruments" tab and select **Map instrument**. The sheet asks for five values:

- **ISIN**, the code the provider names the price by.
- **Token**, the token whose feed receives the price.
- **Price field**, the field that holds the price in a delivery.
- **Price basis** is "Per unit" or "Percent of par". "Percent of par" needs the "Par amount", the value one token stands for in the price currency. The token price is then the quoted price times the par amount divided by 100. A quote of 98.50 with a par amount of 1,000 gives a token price of 985.
- **Currency**, the three-letter ISO code of the price currency, such as EUR.

The sheet shows whether the platform creates a feed for the token, the token's face value, and the price per token that the latest delivery of the ISIN would give. Confirm with your PIN. When the source is active and the platform already holds a delivery for the ISIN, that price goes through the checks as the feed's first price. Otherwise the feed waits for the next delivery.

The currency must match the currency of the token's existing price feed, and the platform refuses a different one with [DALP-14712](https://docs.settlemint.com/docs/api-reference/errors). A token whose feed another source already maps cannot be mapped again, and the platform refuses it with [DALP-14710](https://docs.settlemint.com/docs/api-reference/errors). One ISIN can feed several tokens. An active FIX source requests prices for a new mapping within about 10 seconds, and the provider's snapshot then prices the feed.

The table has the columns "ISIN", "Token", "Price field", "Basis", "Currency", "Price", "Last seen" and "Actions". With nothing mapped it reads "No instruments mapped" and "Map an ISIN to a token to publish its price to a feed."

**Unmatched ISINs** lists the ISINs that arrived without a mapping, and "Map" on a row opens the sheet with the ISIN filled in. With none it reads "No unmatched ISINs".

**Unmap** ends a mapping after a confirmation that prices for the ISIN stop reaching the token's feed from this source. The feed keeps its last price, an open held price on that feed is cancelled, and an open stale-feed case for it is resolved.

### Activate the source [#activate-the-source]

Select **Activate** and confirm with your PIN. The source needs a saved credential, or the page says "Add a credential on the Connection tab to activate." After activation, the source fetches on its schedule and publishes the prices that pass the checks.

If a mapped token has nobody who can approve a held price, a callout says "Some tokens have no one who can approve a held price" and names the tokens. Grant the "Feeds manager" role to another person, or the "Governance" role on the token, before a price is held. Without one, a held price waits with nobody able to decide it.

## Decide a held price [#decide-a-held-price]

A held price appears in two places. The **Held prices** tab of the source lists it, with the number of open held prices in the tab label and the columns "Instrument", "Last published", "Received" and "Reason". With none it reads "No held prices".

The **Actions** page shows a row that names the ISIN and the source, with "Review held price", for each price you may decide. A held price with nobody eligible to decide it reads "No one can approve this yet".

Open it to see the **Review held price** sheet. It shows the "Source", the "Received price", the "Last published" price, the "Change" against the source's hold tolerance, the "Price field", the "Observed" time and the "Reason held", which reads "Moved past tolerance" or "Correction".

The **Evidence** section shows the record, its sequence number, when it was recorded and the evidence digest, and "Show the raw payload" opens the provider's message.

Compare "Received price" with "Last published" and the "Reason held". Select **Approve** to publish the price, or "Reject" and give a reason. Both ask for your PIN. A price you may not decide says "This price needs another approver."

If the platform refuses your decision, the sheet names the reason and shows the current state: "A newer price was published", "The price changed since you opened it", "This price is past its bound", "Someone already decided this price", "This price changed while you were deciding", "The source is paused" or "The source has stopped". Read the sheet again before you decide a second time. A paused source can still have a held price rejected, and cannot have one approved.

Note (Governors review from Actions): A governor of a token who is not a feeds manager does not see "Data feeds" in the sidebar. The "Review held price" row in "Actions" opens the **Held prices** tab, which lists only the prices that governor may decide. The governor cannot read the source itself, so the page shows no source settings, and the evidence shows only the record that produced the price.

## Review deliveries [#review-deliveries]

The **Deliveries** tab lists each delivery with the time it was "Received", its "Status", its "Records", and how its prices settled: "Rejected", "Accepted", "Dropped", "Held" and "Published". "Status" reads "Received", "Failed validation", "Malformed file", "Evidence lost" or "Blocked egress".

Select **Load older deliveries** for earlier ones. With none the tab reads "No deliveries yet" and "Run Test connection on the Connection tab to see the egress IP to allow."

## Fetch, pause and resume a source [#fetch-pause-and-resume-a-source]

The source page header shows "Instruments", "Published today", "Held" and "Last delivery". "Published today" counts from 00:00 UTC.

- **Fetch now** asks an active SFTP, Bloomberg or LSEG source to fetch at once instead of waiting for its schedule. It asks for no PIN. The button reads "Fetching" while it runs, then says how many deliveries the fetch produced, or "Nothing new from the provider". A FIX source streams its prices and offers no "Fetch now". The person who requests a fetch cannot decide a price it holds.
- **Source actions** holds "Pause", "Resume" and "Rotate credential". A paused source publishes nothing. "Resume" asks for your PIN.

## Replace or remove the credential [#replace-or-remove-the-credential]

Choose "Source actions" › **Rotate credential**. It opens the "Replace credential" sheet, which reads "Enter the new credential. The previous one stays in use until the provider accepts the new one."

Select **Replace credential**. The Console confirms "Credential replaced". Rotating the credential does not exclude you from deciding held prices.

On the "Connection" tab, the credential panel shows the last characters the saved credential ends in and its version, never the credential. It offers "Replace", "Add credential" and **Remove**. "Remove" deletes the credential after your PIN, and an active source refuses the removal, so pause it first.

The settings panels on the "Connection" tab edit the connection, the publishing values and the timing. **Save** asks for your PIN.

## Retire a source [#retire-a-source]

**Retire source**, on the "Connection" tab, ends the source for good after a confirmation. The source stops fetching, its feed and ISIN mappings are freed for another source, it cannot be activated again, and its held prices still waiting for a decision are cancelled. A retired source keeps its settings read-only.

## Read the source list [#read-the-source-list]

The **Sources** tab lists each source with "Source", "Protocol", "Instruments", "Last delivery" and "Status", and "Search sources" filters it by name. A source that has delivered nothing reads "No delivery yet". An empty list says "No price sources yet".

"Status" reads "Draft", "Active", "Paused", "Retired", "Retrying" or "Needs attention". "Retrying" means the last fetch failed and the source tries again on its own. "Needs attention" carries the reason: the provider refused the credential, a connection setting needs a change, or the last delivery could not be read.

## Connection fields [#connection-fields]

The **Source** section holds the "Name". The fields in the other sections follow the delivery method:

| Method | Fields |
| --- | --- |
| File session | **Host**, **Port**, **Username**, **Remote path**, **Temporary file suffix**, **Time zone**, and the column names **ISIN column**, **Price column**, **Currency column**, **As-of column** and **Price type column** (leave the last empty when the file holds one price type) |
| FIX session | **SenderCompID**, **TargetCompID**, **TLS server name**, **TLS**, **Session start**, **Session end**, **FIX version**, **Reset sequence numbers** (**Never**, **On every logon** or **On the first logon of a session**) and **Entry types**, each a **MDEntryType** code mapped to a **Price type**, used once |
| Vendor request | **Account**, "Catalog", **Request fields**, separated by commas, **Run at**, as HH:mm times separated by commas, and **Credentials expire (optional)** |

The **Credential** section asks for a "Credential type", "Password" or "Private key", with "Password" or "Private key" and "Passphrase (optional)" to match, or for a vendor "Logon username", "Client ID" and "Client secret". The credential is stored in the platform secret store, is write-only and is never shown again. Select "Cancel" to leave the page without saving.

## Held prices and the second approver [#held-prices-and-the-second-approver]

A price that moves further from the last published price than the source's hold tolerance, or that corrects a price the source already delivered for the same instrument, price type and observed time, is a held price. What happens to it depends on the organisation's **Prices** approval rule, in the "Approvals" section of [General](https://docs.settlemint.com/docs/console/organisation-settings/general#approvals):

- With "Prices" set to **Second person required**, the price waits in a queue and nothing is published until a second person approves it. This maker-checker control covers held prices only.
- With "Prices" set to **Not required**, the platform publishes the price without a second person and records it as not approved by a second person. Actions shows it as "No second approval (approval off)".

Every approval rule starts off in a new organisation, so turn **Prices** on before you activate a source if held prices must be reviewed.

When the rule is on, a feeds manager or a governor of the token decides the held price. A person who set up the source, changed its settings, mapped or unmapped an instrument, trusted its host key, or requested the delivery with **Fetch now** cannot decide it. Rotating the credential does not exclude you. This rule keeps one person from deciding a held price on a source they control. It does not cover a value published by hand on Data feeds or Token pricing, which a trusted issuer publishes with no second person, or a price that moves less than the hold threshold.

## What the platform checks before it publishes [#what-the-platform-checks-before-it-publishes]

Every delivered price becomes an observation with its ISIN, price, currency, price type, observed time and source. The raw delivery is kept off chain as evidence with its hash. The checks run in this order, and the first that applies decides the outcome:

1. A repeat of a price already recorded, with the same value, is dropped as a duplicate.
2. A price at or below zero is refused as invalid.
3. A price for an ISIN with no mapping is recorded as unmapped and listed under **Unmatched ISINs**.
4. A token price, after the price basis is applied, that the feed's decimals cannot hold exactly is refused as invalid.
5. A currency other than the feed's currency is refused as a currency mismatch. It is not held.
6. An observed time earlier than the feed's latest is refused as out of order, and its time is not moved forward. A time more than 60 seconds ahead of the chain is refused as future dated. A time up to 60 seconds ahead waits until chain time reaches it.
7. A different value for the same instrument, price type and observed time is a correction and is held. A FIX message with a higher sequence number than each earlier price that differs from it is not a correction.
8. A move from the last published price beyond **Hold above (percent)** is held.
9. The first price of a feed, a move of at least the publish threshold, or a newer price after the heartbeat interval is published. Any other price is skipped.

A held price then follows the organisation's **Prices** approval rule, as described in [Held prices and the second approver](#held-prices-and-the-second-approver).

A feed has at most one open held price. A later price that would also be held attaches to it as the latest candidate, and an approval publishes that newest candidate. A later price that passes the checks replaces the held price. Freshness counts from the provider's observed time, not from the moment of publishing, so a late approval does not make a feed look fresher than the provider's price is.

## When a feed goes stale [#when-a-feed-goes-stale]

The platform checks every mapped feed once a minute against the chain's time. A feed is stale when its latest observed price is older than the staleness bound: the feed's staleness window, its own or the global default, when that window is finite, else the source's **Stale after**. A feed with no price yet counts from the time it was mapped. A feed with neither bound is not judged. A paused source is still judged, and a retired one is not.

For each stale episode the platform opens one operations case. The "Cases" tab of [Custody](https://docs.settlemint.com/docs/console/organisation-settings/custody) lists it as **Stale price feed**. Only an organisation owner or a platform administrator sees that tab, whether or not the custody books are turned on. The case detail names the token, the bound, since when the feed is stale, the source and the cause:

- The source is paused.
- The source is failing with a transient, credential, configuration or data failure.
- A price is held awaiting review.
- A price is awaiting custody approval before it is published.
- Deliveries since the last publish were dropped as older than the feed's newest price.
- The latest delivery could not be published.
- The latest delivery was refused by the checks.
- The latest delivery has been received but not processed yet.
- The source has delivered no price since the last publish.

The case resolves when a fresh price lands, when the feed is unmapped, or when the source is retired. A feed that turns fresh and then stale again reopens it. Platform operators also get a stale-feed metric and alert rule, described in [Price source prerequisites](https://docs.settlemint.com/docs/deployment/price-source-prerequisites).

## You should see [#you-should-see]

- Open the token's "Placement" tab and read the **Price** card in the "Price feeds" section. "Price from" names the source and the price field, and "Vendor" names Bloomberg or LSEG for a vendor source. The card shows when the provider observed the price, when it was published and by whose approval for a held price, the operations signer under "Signed by", and "Usable until".
- **View evidence** opens "Price evidence", the record the provider delivered for that price. On the source, the "Deliveries" tab lists each delivery and how its prices settled.

## Troubleshooting [#troubleshooting]

**A source needs attention**

Open the source and read the status. If the provider refused the credential, replace it from **Source actions**. If a
connection setting needs a change, the "Connection" tab names it. Check the timing too: the heartbeat, the expected
interval and the expected lag together must stay shorter than the staleness bound. If the last delivery could not be
read, open "Deliveries" and check the status of the latest one. A source stopped by a credential or configuration
failure publishes nothing until you change the cause, then select "Pause" and then "Resume" in "Source actions".

**A delivery shows “Blocked egress”**

The provider refused the platform's outbound address. Run **Test connection** on the "Connection" tab to see the
egress IP, and ask the provider to allow it.

**A price that moved past the tolerance was published without review**

The organisation's "Prices" approval rule is **Not required**. Turn it on in the "Approvals" section of General.
Prices delivered after that wait for a second person.

**Nobody can approve a held price**

The row on the **Held prices** tab reads "No one can approve this yet", and its review sheet reads "No eligible
approver". Only a feeds manager or a governor of the token can approve a held price, and never a person who set up the
source or requested the delivery. Grant the "Feeds manager" role to another person, or the "Governance" role on the
token. Then open the price again.

**An ISIN arrives but no price reaches the feed**

Check **Unmatched ISINs** on the "Instruments" tab: an ISIN with no mapping publishes nothing. Check that the source
is active, because a draft or paused source publishes nothing. Check that the mapping's currency matches the currency
of the token's feed. Then check "Deliveries" for how the prices settled.

**I cannot approve a price I expected to decide**

You set up the source, changed its settings, mapped or unmapped an instrument, trusted its host key, or requested the
delivery. Any of these puts you in the group that cannot decide its held prices. Ask another feeds manager, or the
governor of the token, to decide it.

**The “Price” card shows “Stale”**

The price is older than the feed's staleness window on chain time. Open the **Stale price feed** case on the "Cases"
tab of Custody, which names the cause. A held price waits for review, a paused source publishes nothing, and a source
that stopped delivering needs its provider checked.

## API routes [#api-routes]

The same work is available through the [Platform API](https://docs.settlemint.com/docs/api-reference/v2) under `/api/v2/price-sources` and `/api/v2/held-prices`. A feeds manager uses them with a signed-in session or an API key, and a governor reads and decides the held prices of their own tokens. Activating a source, editing its settings, setting or removing its credential, trusting a host key, mapping instruments and deciding a held price need a signed-in session and wallet verification, so an API key is refused for them. [Read and submit price feeds](https://docs.settlemint.com/docs/api-reference/guides/feeds) lists the routes and their error codes.
