Skip to content

Saved Payment Methods

Taxi & Private HireProductsCustomer › Saved Payment Methods

Generally available

Tokenised cards on file for a customer. The processor holds the real card data; we store only the opaque token, brand, and last-four for display. Multiple cards per customer with at most one default. Removal is soft-delete so historical TripPreAuth rows keep referential integrity.

Example request

POST /client/{clientId}/customer/{customerId}/payment-method

See the API reference for the full request and response schema.

Endpoints

MethodPath
POST /client/{clientId}/customer/{customerId}/payment-method · primary
DELETE /client/{clientId}/customer-payment-method/{paymentMethodId}
GET /client/{clientId}/customer-payment-method/{paymentMethodId}
GET /client/{clientId}/customer/{customerId}/payment-method
POST /client/{clientId}/customer-payment-method/{paymentMethodId}

Full request/response schemas and an interactive explorer will live in the API reference (coming soon).

Use cases

Operator flows that exercise this feature.

Add a payment method

config risk: low

Register a card / wallet against a customer.

  1. POST /client/{clientId}/customer/{customerId}/payment-method

Fields

FieldTypeDescription
customer Customer Owning Customer. `#[Ignore]`d outbound — the payment method is always loaded via the customer scope, never serialised back with its parent reference.
processorName string Upstream processor identifier ("mockpay", future "stripe" / "adyen"). Multi-processor tenants can carry methods from each side-by-side; the processor name disambiguates which adapter to call for capture / refund.
processorTokenId string Opaque processor token (`tok_xxx` / `pm_xxx`). Persistent reference for preauth + capture — not a credential by itself but never serialised outbound (no `#[Groups]`) to minimise blast radius (XSS, screenshot, browser cache). Deserialisation still works for create/update flows since the input pipeline is group-agnostic.
last4 string Last four digits of the card PAN, for display only. Safe to surface — the processor token (`processorTokenId`) is the real reference.
brand string Card brand label ("Visa", "Mastercard", "Amex") sourced from the processor at tokenisation. Drives the brand-icon picker on the FE.
expiryMonth smallint Card expiry month (1–12). Combined with `expiryYear` to drive the FE expired-card warning + the soft-decline retry path.
expiryYear smallint Card expiry year (4-digit). Paired with `expiryMonth`.
isDefault boolean Marks this card as the customer's default at preauth time. Repository validator enforces at most one default per customer; setting `true` on a new card flips the existing default to `false` in the same transaction.
deletedAt integer
deletedBy bigint
clientId bigint Tenant scope. Every tenant-aware entity carries this; `ClientFilter` enforces row-level isolation on read; the multi-tenancy routing layer (`/client/{clientId}`) sets it at create time. Surfaced only under `admin` / `tripLog` groups — never to end users.
internalKey string Optional client-supplied external reference / idempotency key. When present, lets external systems correlate platform-side records back to their own source-of-truth ids. Not persisted to a column — populated by the request handler when the caller sets it.
__objectType string Discriminator string (entity class short-name) emitted alongside the id in serialized output. Resolved at read time by `getObjectType()`; lets the FE dispatch entity-specific rendering without inspecting the URL.
id bigint Snowflake-style primary key (unsigned BIGINT). Generated by `IdFactory` at create time; surfaced to the FE / API as a `G`-prefixed string and stripped back to plain bigint server-side before Doctrine lookup.
createdDate integer Unix timestamp the row was first persisted. Set in the entity's PrePersist hook; never rewritten on subsequent updates.
updatedDate integer Unix timestamp the row was last touched. Bumped on every commit that hits the Doctrine UoW for this entity; drives FE invalidation + the listing change cursor.
passiveUpdatedDate int Read-through alias for `updatedDate` exposed under different serializer groups. Lets the FE distinguish "real edit" from "background touch" projections without changing the underlying column.
listingUpdatedDate int Listing-projection timestamp surfaced only under the `listMode` group. Driven by `TripCache` and other listing-shape refreshers separately from `updatedDate` so a listing rebuild doesn't trigger detail-page invalidation.