Requests
A request names what it acts on in its URL, and says what to do with it in its body, a JSON object. The shop is the API key's.
Environments
| Host | Environment |
|---|---|
api.gjold.com |
Production, where payers pay for real. |
api.gjold.dev |
The test environment, for developing integrations, where no money moves. |
The two are not connected: an account, a key, or an ID on one means nothing on the other. Only we create accounts in the test environment: write to us and say what you need one for.
URLs
A request's URL is https://api.gjold.com/v1/, then the request's
path. A path that names a transaction or a subscriber has its ID, and
then the action:
https://api.gjold.com/v1/new
https://api.gjold.com/v1/seq/{seq}
https://api.gjold.com/v1/transactions/{trnid}/{action}
https://api.gjold.com/v1/subscribers/{subid}/{action}
There is no shop ID in the URL: a request acts on the shop of its API key.
A URL that fits no request is answered 404 Not Found, and a known URL
with the wrong method, such as a GET of /v1/new,
405 Method Not Allowed.
IDs
| ID | What it names |
|---|---|
{trnid} |
A transaction, which a paid link or a charge of a subscriber creates: its "id" in seq's changes, or in the answer to Charge subscriber. |
{subid} |
A subscriber: its "id" in seq's changes. |
{seq} |
A number in the shop's sequence of changes: see Seq. |
A payment link has no ID in v1: Create payment link answers with its URL alone, and seq tells you of the transaction that paying it creates.
Your shop ID is the part of your API key before the colon. Shop, transaction, and subscriber IDs are positive integers, written in decimal without leading zeros, and never reused. A shop's transactions are numbered from 1 in the order they were created, and so are its subscribers. Store an ID as a 64-bit integer, or as a string.
Request bodies
A POST request has a body: one JSON object, encoded as UTF-8, of at
most 32 KiB. We don't read Content-Type, but send
application/json, which is what it is.
The body must be valid JSON. If it isn't, the request fails with
400 invalid json in {where}: {why}, where {where} is the path of the
field at fault, as in items[1].total, or json root object for the
body as a whole. See Errors.
v1 is lenient with what it can read, and quiet about what it can't:
- Unknown fields are ignored, so that a field that you misspelled goes unnoticed. Check your spelling against the field tables.
- Types are as each field table gives them. A field of another
type, or
null, is ignored, as if you had left it out, and is not an error. A misspelled field and a mistyped one fail the same way: the request goes through without them. - Strings may contain any Unicode text, which we clean up before we
store it: each white space character, such as a tab or a newline,
becomes a space, other control characters are removed, and spaces at
the ends are trimmed. A string that is empty after that is the same
as no string at all. Create payment link, Create subscriber, and
Renew subscriber also take a number or a boolean for a string, and
drop bytes that are not UTF-8, where the other requests fail with
invalid utf in string. - Integers are JSON numbers without a fraction or an exponent, so
2, not2.0or"2". - Amounts are strings, as
"99.95 DKK", never JSON numbers. See Amounts.
Responses
A request that succeeds is answered with 200 OK and a JSON object,
which is {} for capture and refund, which only act. Its
Content-Type is application/json. A request that fails is answered
with another status and a line of text. See Errors.
Every response has these headers:
| HTTP header | Why |
|---|---|
Cache-Control: no-store |
No answer is to be cached, by you or anything in between. |
Strict-Transport-Security: max-age=63072000 |
Browsers and clients that honour it use HTTPS only, for two years. |
X-Content-Type-Options: nosniff |
The Content-Type is what it says. |
Compatibility
The API's version is in its URL, /v1/. Within a version, we may add
to the API, but not change or take away:
- We may add requests, optional request fields, response fields, and
new values of fields that list their values, such as a change's
"type", a transaction's"act", a card's"brand", or a transaction's"services". Write your client to skip what it doesn't know. - We may add error messages, and reword them. Branch on the status, not on the message.
- We don't remove or rename a field, change its type or meaning, or make an optional field required.
What these rules don't allow is in v2, at /v2/, which launches in
early 2027. v1 stays beside it, and is supported for years after.