Get started
Authentication
A call that takes a body needs a key. A call you could open as a link does not.
cc_test_…Anybody’s, from one call. 30 days.cc_live_…Issued to a lender by Creditcrest, for the products it uses.- 1
Get a sandbox key
No account, no card.
curl -s -X POST https://app.creditcresttechnologies.com.au/v1/keys/sandboxconst res = await fetch('https://app.creditcresttechnologies.com.au/v1/keys/sandbox', { method: 'POST', }); console.log(await res.json());import json, urllib.error, urllib.request req = urllib.request.Request( "https://app.creditcresttechnologies.com.au/v1/keys/sandbox", method="POST", ) try: with urllib.request.urlopen(req) as res: print(json.load(res)) except urllib.error.HTTPError as e: print(json.load(e))Response · 201trimmed { "key": "cc_test_eyJ2Ijox…", "id": "8iinormn", "mode": "test", "expires": "2026-12-10" } - 2
Send it
In the
Authorizationheader, on every call. Keep it in an environment variable, never in source code.curl -s -X POST https://app.creditcresttechnologies.com.au/v1/statement \ -H "authorization: Bearer $CREDITCREST_KEY" \ -H 'content-type: text/csv' \ --data-binary @statement.csvimport { readFile } from 'node:fs/promises'; const res = await fetch('https://app.creditcresttechnologies.com.au/v1/statement', { method: 'POST', headers: { authorization: `Bearer ${process.env.CREDITCREST_KEY}`, 'content-type': 'text/csv', }, body: await readFile('statement.csv'), }); console.log(await res.json());import json, os, urllib.error, urllib.request req = urllib.request.Request( "https://app.creditcresttechnologies.com.au/v1/statement", data=open("statement.csv", "rb").read(), headers={ "Authorization": "Bearer " + os.environ["CREDITCREST_KEY"], "Content-Type": "text/csv", }, method="POST", ) try: with urllib.request.urlopen(req) as res: print(json.load(res)) except urllib.error.HTTPError as e: print(json.load(e))
Sandbox and live
The prefix says which a key is, so a key pasted in the wrong place is plain at a glance and to secret scanners.
| Sandbox | Live | |
|---|---|---|
| Begins | cc_test_ | cc_live_ |
| From | Anybody, one call: POST /v1/keys/sandbox | Creditcrest, to a lender, for the products it uses |
| Lasts | 30 days | Until it is revoked, or its expiry date if it has one |
| Charged | Never | At the published prices |
| Limit | 60 calls a minute | 600 calls a minute |
| A lender’s records | Sandbox and test records only | Real records, once the lender is live |
| The answer says | x-creditcrest-mode: test | x-creditcrest-mode: live |
Limits
Per key, per minute: 600 calls on a live key and 60 on a sandbox key. Sandbox keys themselves: 5 a minute from one network address. Over a limit, the answer is 429 rate_limited with Retry-After.
When a key is refused
| Status | Error | |
|---|---|---|
401 | key_required | The call needs a key and none was sent. |
401 | invalid_key | The key was not issued by Creditcrest, was altered, or is not whole. |
401 | expired_key | The key is past its expiry date. |
401 | revoked_key | The key was withdrawn. |
403 | out_of_scope | The key is not for this product. |
403 | wrong_lender | The key is another lender’s than the one in the address. |
403 | test_key | A test key cannot read or change a lender’s real records. |
409 | live_key | A live key was sent to a lender whose records are not live yet. |
422 | sandbox_only | The lender is not keeping real records yet, so a live key is refused. |
429 | rate_limited | Too many calls this minute on this key, too many sandbox keys from one network address, or too many codes asked for from one network address. |
503 | keys_unavailable | Keys cannot be checked or issued here just now. |
What an answer says
| Header | On | |
|---|---|---|
Request-Id | Every answer | Which request it was. Quote it to support. |
Creditcrest-Version | Every /v1 answer | The API’s version: the date of the newest changelog entry, now 2026-11-09. |
x-creditcrest-key | A keyed call | The id of the key that made it. Never the key. |
x-creditcrest-mode | A keyed call | test or live. |
RateLimit-Policy | A keyed call | The key’s limit: "live";q=600;w=60 is 600 calls in 60 seconds. |
Retry-After | A 429, and some 503s | Seconds to wait before trying again. |
Idempotent-Replayed | A POST sent again | true when the call was sent before under the same Idempotency-Key: counted once. Retrying safely. |
What is recorded
Each call made with a key is counted — the key’s id, the endpoint, the status and the time — so it can be billed. A sandbox key’s calls also keep the error code of a call that failed, and are deleted after 35 days. Nothing you send is kept or logged. GET /v1/usage shows your month and what it comes to.
GET/v1/keysOpen ↗
Describes this API: what it takes and what it returns.
POST/v1/keys/sandbox
A sandbox key, straight away, for 30 days. No account.
GET/v1/keys/meKey
What the key you sent is: its id, lender, mode, scopes and expiry. Never the key itself.
GET/v1/usageKey
Your month: every call and check counted, each application decided on your hosted pages and each advance, and what they come to at the published prices on your own terms, Launch included. Test and sandbox use, and refused calls, are never charged. The price is what you pay: GST is never added on top. total is what is payable, and gstIncluded the GST inside it once Creditcrest is registered for GST. spend is the month so far, its estimate for the month, and your spend alert with how far through it the month is.
| Query | |
|---|---|
month | YYYY-MM, a calendar month in Sydney; this month when left out |
GET/v1/admin/usage
Creditcrest’s own: every lender’s month, priced, for invoicing. Needs Creditcrest’s admin token, not a key.
| Query | |
|---|---|
month | YYYY-MM, a calendar month in Sydney |
format | csv for a spreadsheet; JSON otherwise |
lender | one lender’s id, to run it for one |
GET/v1/admin/invoices/:lender
Creditcrest’s own: one lender’s invoice for a month — its number, dates, lines, price list version, Launch and total, and on a tax invoice the GST the total includes (none is added) — as JSON or a PDF. The first time it is final it is kept, with its SHA-256, and that invoice is answered ever after, byte for byte. Needs Creditcrest’s admin token, not a key.
| Query | |
|---|---|
month | YYYY-MM, a calendar month in Sydney |
format | pdf for the document; JSON otherwise |
issued | YYYY-MM-DD, when it is issued later than the first day after the month |
remake | 1 to make an issued month again and say whether it still agrees (409 when it differs) |
adjustment | n for the month’s nth adjustment note |
POST/v1/admin/invoices/:lender/adjustments
Creditcrest’s own: an adjustment note for an issued month made again — its own document, naming the invoice it adjusts and that invoice’s SHA-256, and changing what is owed by the difference. The issued invoice is never changed. Needs Creditcrest’s admin token.
| Query | |
|---|---|
month | YYYY-MM, the issued month |
format | pdf for the document; JSON otherwise |
{reason}: why it is issued, at most 300 charactersPOST/v1/admin/usage
Creditcrest’s own: puts back counts that could not be written at the time, each once. Needs Creditcrest’s admin token.
{rows: [{id, lender, mode, item, kid, status, of, amount, at}]}