Errors
Install AI tools
Give your assistant up-to-date guidance for our APIs, with our plugin or without it.
The plugin is still under development. See the AI tools page for details.
- Claude Code
- Cursor
- Codex
- Without installing
Run both commands, in order.
claude plugin marketplace add vippsas/agent-toolkit
claude plugin install vipps-developer@agent-toolkit
Open Settings, then Plugins.
Add vippsas/agent-toolkit as a plugin marketplace, then install the "vipps-developer" plugin.
For the app, add the marketplace "vippsas/agent-toolkit" and then install "vipps-developer". For the CLI, run the following commands.
codex plugin marketplace add vippsas/agent-toolkit
codex plugin add vipps-developer@agent-toolkit
Paste this into any assistant.
Read https://github.com/vippsas/agent-toolkit/blob/main/plugins/vipps-developer/README.md for Vipps MobilePay integration guidance.
For troubleshooting, see the full instructions.
This API is in development and not yet available.
The Loyalty API reports errors the same way as the other Vipps MobilePay APIs: an
RFC 9457 problem-details body served as application/problem+json.
See Troubleshooting errors for the platform-wide format.
Every request to POST:/loyalty/v1/events is validated synchronously before it is accepted,
so the normal outcomes are 202 Accepted or a 4xx problem that names exactly what to fix.
A 5xx is an operational problem on our side, not something the payload can fix.
Response shape​
{
"type": "https://developer.vippsmobilepay.com/docs/APIs/loyalty-api/errors/#validation-error",
"title": "The event failed validation",
"status": 400,
"detail": "The event breaks 2 validation rule(s). See extraDetails for each field. Rules: https://developer.vippsmobilepay.com/docs/APIs/loyalty-api/errors/#validation-rules",
"instance": "/loyalty/v1/events",
"traceId": "3f1c2b6e-8e4d-4b0a-9a1e-6d3f8c2a7b11",
"extraDetails": [
{ "name": "payload.phoneNumber", "reason": "must be an E.164 phone number, e.g. +4712345678" },
{ "name": "payload.coupons[1].id", "reason": "duplicate id within the collection" }
]
}
| Field | Meaning |
|---|---|
type | Stable identifier of the problem. Match on this, never on title or detail. It is a URL to the matching section on this page. |
title | Short human-readable summary. Fixed per type. |
status | HTTP status code, as an integer. |
detail | Human-readable explanation for this occurrence. May be reworded. |
instance | The request path. |
traceId | Identifier of this request in our logs. Quote it when contacting support. |
extraDetails | Field-level problems. name is a JSON path relative to the request body, for example payload.stampCards[3].usage.usesLeft; array items are indexed. name is omitted when the whole body is unreadable. Present on 400 responses only. |
Problem types​
Each type starts with https://developer.vippsmobilepay.com/docs/APIs/loyalty-api/errors/# followed by one of the identifiers below.
not-authorized​
401 Unauthorized. The Authorization header is missing, or the merchant-level access token is expired, signed by the
wrong issuer, issued for another audience, lacks the merchant_id claim, or lacks the loyalty-api:write scope.
Request a new token from POST:/miami/v1/token as
described in the Quick start.
malformed-event​
400 Bad Request. The body could not be read as a Loyalty API event: it is not valid JSON or not a single JSON object,
action is missing or unknown, a required field is missing, or a value has the wrong JSON type.
Types are strict: "100" is not an integer, 123 is not a string, "false" is not a boolean and 7.5 is not an integer.
Trailing content after the JSON object is rejected. extraDetails has one entry naming the field.
Fix the payload and resend; retrying unchanged will fail again. See the actions for the schema of each event.
validation-error​
400 Bad Request. The body is well-formed but breaks one or more validation rules.
Every violation is listed in extraDetails, so one round trip is enough to fix the payload.
payload-too-large​
413 Payload Too Large. The request body exceeds 240 KiB. Split collection snapshots into several members' events or
shorten free-text fields.
unsupported-media-type​
415 Unsupported Media Type. Content-Type is missing or is not application/json. Parameters such as charset=utf-8 are allowed.
internal-error​
500 Internal Server Error. The event was valid but could not be queued for processing. It is safe to retry with the same
eventId; duplicates are tolerated downstream. Quote traceId if the problem persists.
Validation rules​
These rules are enforced on every event in addition to the required fields and types in the
API reference. A violation returns validation-error.
| Field | Rule |
|---|---|
eventId | Non-blank, at most 128 characters. |
timestamp | RFC 3339 date-time, not more than 5 minutes in the future. Any age in the past is accepted. |
payload.contactId | Non-blank, at most 256 characters. |
payload.phoneNumber | E.164: + followed by 7 to 15 digits, first digit not 0. No spaces or separators. |
bonusPoints.balance, bonusPoints.cashPoints | Not negative. |
membershipTier.tierName | Non-blank, at most 200 characters. |
membershipTier.points, membershipTier.pointsToNextLevel | Not negative. |
Coupon and stamp card id, parentId | Non-blank, at most 256 characters. |
Coupon and stamp card heading | Non-blank, at most 200 characters. |
Coupon and stamp card detailHeading | At most 200 characters. |
Coupon and stamp card description | At most 4000 characters. |
redemption.link, bonusCheck.link | Absolute http or https URL, at most 2048 characters. |
redemption.promotionCode | At most 100 characters. |
usage.timesUsed, usage.usesLeft | Not negative. |
coupons[], stampCards[] | At most 500 items; id unique within the array. Send an empty array to clear the member's collection. |
bonusCheck.id | Non-blank, at most 256 characters. |
bonusCheck.name | At most 200 characters. |
bonusCheck.amount | At least 1. |
bonusCheck.currency | Three upper-case letters (ISO 4217), for example NOK. |
bonusCheck.validUntil | Not before bonusCheck.validFrom. |
payload.id on *.deleted | Non-blank, at most 256 characters. |
The timestamp rule exists because we use your timestamp to discard stale updates. A timestamp far in the future
would freeze the member's state until that instant. A few minutes of clock skew is tolerated.
Unknown JSON properties are ignored.
Existence of the member, coupon, stamp card or bonus check is not checked when the event is accepted.
A 202 confirms that the event is valid and queued, not that it has been applied.