Requests
A request names the object it acts on in its URL, and says what to do with it in its method and its body, a JSON object.
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
Every object has a URI, which names its shop, the database it is in, and its ID there:
{shopid}:{db}:{id}
A request's URL is https://api.gjold.com/v2/, then as much of a URI
as the request needs, then the action, if the request has one. Without
an action, the method says what the request does, as a DELETE deletes
the object:
https://api.gjold.com/v2/{shopid}:{db}/{action}
https://api.gjold.com/v2/{shopid}:{db}:{id}/{action}
https://api.gjold.com/v2/{shopid}:{db}:{id}
A URL that fits no request is answered 404 Not Found, and a known URL
with the wrong method 405 Method Not Allowed.
IDs
| Database | Its IDs |
|---|---|
pay |
Payment links. A link's ID is the "id" that Create payment link answers with: 12 to 48 letters and digits. |
trn |
Transactions, which a paid link or a charge of a subscriber creates. A transaction's ID is its "id" in seq's changes, or in the answer to Charge subscriber. |
sub |
Subscribers. A subscriber's ID is its "id" in seq's changes. |
seq |
The changes themselves, by number: see Seq. |
Your shop ID is in the dashboard. 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. A request without fields to
send, such as a void, sends {}.
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.
- Unknown fields are ignored, so that a request written for a later version of the API, or with a field that you misspelled, still goes through. Check your spelling against the field tables.
- Types are as each field table gives them. A field of another type
is an error, and so is
null: leave the field out instead. - 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.
- 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 the requests that only act, such as a capture. 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, /v2/. 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, but for the ones to
branch on: a
402's first word,transientorpermanent, and a409's whole message, as Errors lists them. Branch on the status, and on those. - We don't remove or rename a field, change its type or meaning, or make an optional field required.
A change that breaks these rules goes in a new version, with its own URL, beside the old one.