Skip to content
WorkspaceDarkLight
Contents

Get started

Authentication

A call that takes a body needs a key. A call you could open as a link does not.

Sandboxcc_test_…Anybody’s, from one call. 30 days.
Livecc_live_…Issued to a lender by Creditcrest, for the products it uses.
  1. 1

    Get a sandbox key

    No account, no card.

    curl -s -X POST https://app.creditcresttechnologies.com.au/v1/keys/sandbox
    const 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. 2

    Send it

    In the Authorization header, 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.csv
    import { 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.

SandboxLive
Beginscc_test_cc_live_
FromAnybody, one call: POST /v1/keys/sandboxCreditcrest, to a lender, for the products it uses
Lasts30 daysUntil it is revoked, or its expiry date if it has one
ChargedNeverAt the published prices
Limit60 calls a minute600 calls a minute
A lender’s recordsSandbox and test records onlyReal records, once the lender is live
The answer saysx-creditcrest-mode: testx-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

StatusError
401key_requiredThe call needs a key and none was sent.
401invalid_keyThe key was not issued by Creditcrest, was altered, or is not whole.
401expired_keyThe key is past its expiry date.
401revoked_keyThe key was withdrawn.
403out_of_scopeThe key is not for this product.
403wrong_lenderThe key is another lender’s than the one in the address.
403test_keyA test key cannot read or change a lender’s real records.
409live_keyA live key was sent to a lender whose records are not live yet.
422sandbox_onlyThe lender is not keeping real records yet, so a live key is refused.
429rate_limitedToo 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.
503keys_unavailableKeys cannot be checked or issued here just now.

What an answer says

HeaderOn
Request-IdEvery answerWhich request it was. Quote it to support.
Creditcrest-VersionEvery /v1 answerThe API’s version: the date of the newest changelog entry, now 2026-11-09.
x-creditcrest-keyA keyed callThe id of the key that made it. Never the key.
x-creditcrest-modeA keyed calltest or live.
RateLimit-PolicyA keyed callThe key’s limit: "live";q=600;w=60 is 600 calls in 60 seconds.
Retry-AfterA 429, and some 503sSeconds to wait before trying again.
Idempotent-ReplayedA POST sent againtrue 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
monthYYYY-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
monthYYYY-MM, a calendar month in Sydney
formatcsv for a spreadsheet; JSON otherwise
lenderone 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
monthYYYY-MM, a calendar month in Sydney
formatpdf for the document; JSON otherwise
issuedYYYY-MM-DD, when it is issued later than the first day after the month
remake1 to make an issued month again and say whether it still agrees (409 when it differs)
adjustmentn 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
monthYYYY-MM, the issued month
formatpdf for the document; JSON otherwise
Body
{reason}: why it is issued, at most 300 characters

POST/v1/admin/usage

Creditcrest’s own: puts back counts that could not be written at the time, each once. Needs Creditcrest’s admin token.

Body
{rows: [{id, lender, mode, item, kid, status, of, amount, at}]}