Quickstart
This guide walks through the first API calls most integrations make: authenticate, read available data, find an indication, submit a subscription request, and retrieve the resulting holding.
We recommend using the sandbox environment while you build and test. OAuth 2.0 is required for production data.
Before you start
You will need:
- Access to the TreasurySpring sandbox environment
- OAuth client credentials or a sandbox API key
- An entity code that your API user can access
- Permission to view indications, subscriptions, and holdings
For building and testing, the sandbox base URL is:
https://api.sandbox.treasuryspring.com/api/v1
Production sits at:
https://api.treasuryspring.com/api/v1
Request flow
1. Authenticate
Request an OAuth access token and send it as a Bearer token.
2. Discover data
List entities and indications available to the API user.
3. Subscribe
Submit an idempotent subscription request for a valid indication.
4. Track the holding
Poll the subscription until holdingUid is present, then reconcile against the holding.
1. Get an access token
Use OAuth 2.0 client credentials to request an access token.
- cURL
- Python
curl --location 'https://api.sandbox.treasuryspring.com/oauth/token' \
-H 'Authorization: Basic <base64_client_id_and_secret>' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=<client_id>' \
--data-urlencode 'client_secret=<client_secret>'
import base64
import requests
basic = base64.b64encode(b"<client_id>:<client_secret>").decode()
resp = requests.post(
"https://api.sandbox.treasuryspring.com/oauth/token",
headers={
"Authorization": f"Basic {basic}",
"Content-Type": "application/x-www-form-urlencoded",
},
data={"grant_type": "client_credentials"},
)
token = resp.json()["access_token"]
Use the returned access token in subsequent requests:
Authorization: Bearer <access_token>
2. Confirm available entities
Start by listing the entities your API user can access. GET/entity
- cURL
- Python
curl -X GET 'https://api.sandbox.treasuryspring.com/api/v1/entity' \
-H 'Authorization: Bearer <access_token>'
resp = requests.get(
"https://api.sandbox.treasuryspring.com/api/v1/entity",
headers={"Authorization": f"Bearer {token}"},
)
entities = resp.json()
Store the relevant entityCode. Most investment endpoints require it.
3. Find an indication
An indication represents an available FTF that can be subscribed to. GET/indication/{code}
- cURL
- Python
curl -X GET 'https://api.sandbox.treasuryspring.com/api/v1/indication/<entity_code>' \
-H 'Authorization: Bearer <access_token>'
resp = requests.get(
f"https://api.sandbox.treasuryspring.com/api/v1/indication/{entity_code}",
headers={"Authorization": f"Bearer {token}"},
)
indications = resp.json()
Choose an indication and store its uid. To re-fetch a single indication later (e.g. to refresh its pricing before subscribing), use GET/indication/{code}/{uid} with the entity code and the indication uid.
4. Subscribe
Submit a subscription request with the indication UID and desired amount. POST/subscribe
- cURL
- Python
curl -X POST 'https://api.sandbox.treasuryspring.com/api/v1/subscribe' \
-H 'Authorization: Bearer <access_token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <unique-request-id>' \
-d '{
"entityCode": "<entity_code>",
"indicationUid": "<indication_uid>",
"amount": 1000000
}'
resp = requests.post(
"https://api.sandbox.treasuryspring.com/api/v1/subscribe",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"Idempotency-Key": "<unique-request-id>",
},
json={
"entityCode": entity_code,
"indicationUid": indication_uid,
"amount": 1_000_000,
},
)
subscription = resp.json()
The subscription may initially be PENDING or ACCEPTED. The resulting holding is not always available straight away in the /subscribe response — step 5 below covers how to track it through to issuance.
To check a prospective subscription without committing to it, call POST/validate first with the same body. It confirms the indication is still available to the entity on the chosen subscriptionDate and that the amount is within the indication's limits, returning the matching indication (with current pricing). A 4xx response means /subscribe would be rejected. See Funding & settlement for details.
A stable, unique Idempotency-Key per subscription request is recommended. If you retry the same request after a network failure, please reuse the same key so we can replay the original response rather than process a duplicate.
5. Poll the subscription
Poll GET/subscription until the subscription has a holdingUid, or until the subscription reaches a terminal unsuccessful status such as DECLINED.
- cURL
- Python
curl -X GET 'https://api.sandbox.treasuryspring.com/api/v1/subscription?entity_code=<entity_code>' \
-H 'Authorization: Bearer <access_token>'
resp = requests.get(
"https://api.sandbox.treasuryspring.com/api/v1/subscription",
params={"entity_code": entity_code},
headers={"Authorization": f"Bearer {token}"},
)
Once holdingUid is present, treat the holding as the source of truth.
6. Retrieve the holding
Use the holdingUid to retrieve the holding. GET/holding/{entity_code}/{holding_uid}
- cURL
- Python
curl -X GET 'https://api.sandbox.treasuryspring.com/api/v1/holding/<entity_code>/<holding_uid>' \
-H 'Authorization: Bearer <access_token>'
resp = requests.get(
f"https://api.sandbox.treasuryspring.com/api/v1/holding/{entity_code}/{holding_uid}",
headers={"Authorization": f"Bearer {token}"},
)
The holding starts as Pending, then moves through its lifecycle. See FTF Lifecycle for the full status flow.
Reconciling against an internal record
Once holdingUid is populated, the holding is your source of truth. The fields you'll typically compare against an internal book entry are:
| Holding field | What to match |
|---|---|
holdingUid | Your internal primary key for this position (stable across status changes — see Identifiers). |
entityCode | Which client organisation this is for. |
productCode + issueDate + maturityDate | The composite "security identity" — productCode alone is not unique. |
obligorExposureCode | Credit exposure (with collateral suffix like [GC] / [WC]). |
cost | Principal applied at issuance. |
maturityValue | Expected payout at maturity (after any MVA). |
yield | Annualised APY. See Yield semantics — Holding.mmyA365F is the same return in MMYA365F format, available if you specifically need it. |
cutoffDatetime | Last point at which the maturity action can be changed. |
Next steps
- Authentication — full OAuth grant-type reference and trusted-system / impersonation patterns.
- Identifiers & keying your records — which fields are stable, which are not.
- Funding & settlement — wire instructions and the millions-vs-absolute-currency rule.
- FTF Lifecycle — subscription-to-holding transitions and maturity actions.
- Errors & responses — what failures look like and how to recover.
- Sandbox guide — what the sandbox can and cannot test.
- API Reference — full endpoint reference while implementing.