Requests and responses
Every endpoint speaks the same JSON. Learn it once here, and the reference only has to tell you what is different.
Base URL#
Send every request over HTTPS to the version you build against:
https://api.welly.no/v1Methods and paths#
Paths name things in the plural, in lower case: /v1/enrolments, /v1/enrolments/{enrolment}. The method says what happens:
| Method | What it does |
|---|---|
GET |
Reads. It never changes anything. |
POST |
Creates something, or does an action such as /cancel. |
PATCH |
Changes some fields of something. |
DELETE |
Removes something. |
A request body is JSON, sent with Content-Type: application/json. A field the endpoint does not know is refused with parameter_unknown, so a typo is never silently ignored.
Resources#
A resource is a JSON object. Its object field says what it is, and its id is a public id that never changes. Keys are in snake_case.
{
"object": "enrolment",
"id": "pe8fdsi3tthy5hsaacus8cg5bfms",
"program": "pmch6aid5frt4rye3ipupwxsn2ux",
"status": "active",
"starts_on": "2026-11-02",
"created": "2026-10-12T09:41:07Z"
}Examples, not endpoints. Objects such as enrolment show the conventions. They are not in the API yet; the reference lists what is.
Ids, times and money#
- Ids are strings such as
pe8fdsi3tthy5hsaacus8cg5bfms. Store them as they are; the first two letters say what kind of thing it is. - Times are RFC 3339 in UTC, ending in
Z:2026-10-12T09:41:07Z. - Dates without a time are
YYYY-MM-DDand mean that day where the member lives:starts_on. - Money is an exact decimal string with its currency, never a floating-point number:
{"amount": "24990.00", "currency": "NOK"}. nullmeans the field is not set.
Members are never named#
The API gives a member by their id. It never gives a member's name, e-mail address, phone number or date of birth, unless an endpoint exists for that purpose and your agreement covers it.
Lists#
An endpoint that returns many things returns a list, a page at a time. See Pagination.
| Field | Type | Meaning |
|---|---|---|
object |
"list" |
Always list. |
data |
array | The page of resources, at most limit of them. |
has_more |
boolean | Whether there is a next page. |
next_cursor |
string or null | Pass it as starting_after for the next page. |
Errors#
A request that fails gets an HTTP status from 400 up and an error object. Act on type and code; the message is for people and may change. See Errors.
{
"error": {
"type": "invalid_request_error",
"code": "resource_missing",
"message": "No such endpoint: GET /v1/pong",
"param": null,
"doc_url": "https://developer.welly.no/docs/errors#resource_missing",
"request_id": "req_6b1d0c9e2f4a4d1c"
}
}Headers#
Every response is JSON, is never cached (Cache-Control: no-store), and has a Welly-Request-Id header.
Keep the request id. Log the Welly-Request-Id of every request. Send it to us when you ask about a request, and we can find it at once.