Skip to content

Repository files navigation

Ecommerce Loyalty — HTTP API

Tests

The HTTP surface over liberusoftware/ecommerce-loyalty: a person's earned standing with a merchant, and the append-only ledger that standing is replayed from.

It presents the domain. It reimplements none of it, holds no business rule, and reads none of the domain's Eloquent models — everything goes through the actions, queries and value objects that package publishes.

The three things worth knowing before you call it

There is no balance column behind this API. A balance is a replay over an ordered ledger of lots, and the replay can fail. So a balance is published with reconcilable on its face, and when that is false points is null — never 0. "You have no points" and "we could not work out how many points you have" are different sentences, and rendering the second as the first is a customer told their points are gone.

The merchant is never accepted and the subject depends on the ability. The merchant comes from the credential, always. The subject comes from the credential under loyalty:read and loyalty:redeem, and from the request body under loyalty:operate and loyalty:privacy. Which applies is decided by the ability an endpoint requires and never by anything a caller sends.

There is no idempotency key. Every write already has a natural key the database enforces: an award on its cause, an enrolment on the subject and programme, a redemption on its cause. A key the client holds is a key the client can change, so one layered on top would be strictly weaker than the constraint already there. Send your own order reference as cause_ref and retry freely.

The endpoints

Mounted at api/loyalty by default.

Ability
GET /programmes/{programme} loyalty:read Currency, timezone, earn rate, point value
GET /programmes/{programme}/rewards loyalty:read What is on offer today, cheapest first
GET /programmes/{programme}/balance loyalty:read The caller's own, replayed
GET /programmes/{programme}/statement loyalty:read The caller's own ledger, with the lots each debit drew from
GET /tiers/{tier}/membership loyalty:read Is the caller currently in this tier
POST /programmes/{programme}/redemptions loyalty:redeem Spend the caller's own points
POST /programmes/{programme}/enrolments loyalty:operate Join a named subject
POST /programmes/{programme}/awards loyalty:operate Put a lot in the ledger
POST /programmes/{programme}/tier-evaluations loyalty:operate Judge a named subject against the tiers
POST /programmes/{programme}/expiry-runs loyalty:operate Retire lapsed lots
GET /programmes/{programme}/liability loyalty:operate What the merchant owes
POST /subject-records loyalty:privacy Export one subject's whole record
POST /erasures loyalty:privacy Erase the subject, keep the arithmetic

The OpenAPI 3.1 document is at resources/openapi/openapi.json, and the suite asserts parity with the router in both directions — including that every operation documents the ability the controller actually enforces.

Failures

Every error body is {"error": {"code", "message", "resubmittable"}}.

resubmittable is the whole classification, and there are only two ways to get it: 422, the input was wrong, and 503, a seam this deployment has not bound was needed and nothing was written. Everything else — 404 and 409 — reached a decision that will not change.

Nothing here is transient, so there is no 429, no 423 and no retry header anywhere. A courtesy retry prompt on a permanent refusal is a lie a surface tells on its domain's behalf, and the suite asserts no message here contains one.

A programme, a tier, a reward or a membership belonging to another merchant answers 404, byte for byte as one nobody ever minted. There is no 403 for a reference that is not yours: a 403 confirms it exists.

Install

Needs the VCS repository entry for the domain package in the host's root composer.json — Composer honours repositories only from there.

composer require liberusoftware/ecommerce-loyalty-api

Composer boots nothing. Enable ecommerce-loyalty and ecommerce-loyalty-api in MODULES_ENABLED.

Read docs/adoption.md before issuing a token: which abilities go where, what each unbound seam means, and the two things a caller must not collapse.

Documentation

Licence

MIT.

About

HTTP API presentation package for the ecommerce-loyalty domain module

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages