Returns a paginated list of vendor cards (corporate cards issued by Cardda). Each row in the response represents a single physical or virtual card and exposes its current status, spending limits, balance, and the user it is assigned to.
The result is scoped per-caller across every company the caller has
permission in (via policy_scope), not by the company-id header — the
header is not consulted for this endpoint, and omitting it still returns
200 with the caller's full permitted scope across companies. To narrow the
results, filter explicitly; user_id is a cardholder filter (it returns
only cards assigned to that user), not a per-company restriction.
- Admins see every card in their permitted scope.
- Company members with the
vendor_cards_managepermission see every
card of the companies they manage. - Regular users see only cards assigned to them (
user_idmatches their
Firebase user id).
The type field (issuing vendor / STI sub-class) is returned to every
caller: it is the model's Single Table Inheritance discriminator column, so
it always serializes into the row (the controller's methods.push(:type) if admin? is a no-op — type is already a column, not a computed method).
Response structure
Each item is a VendorCard plus the following computed fields:
| Field | Description |
|---|---|
spent | Amount spent in the current spending interval, as an integer in the minor unit of the transactions' currency (whole pesos for CLP). Sign-flipped from the negative amount_cents of the spends. |
remaining_balance | Funds still available on the card, as a decimal string in the card currency (not cents). |
preference_restricted_spendable | Spendable amount taking active preferences into account. |
spent_in_vendor_interval | Amount spent in the vendor's billing interval. |
fees_in_vendor_interval | Fees accrued in the vendor's billing interval. |
limit_amount | Hard spending limit (limit_based strategy). |
limit_amount_preference | Pending limit change (waiting to be pushed to the vendor). |
allocated_amount | Funds currently loaded onto the card (allocation_based strategy). |
allocated_amount_preference | Pending allocation change. |
Filtering grammar
Every column documented below accepts the MongoDB-style operators described in Filters: $gt, $gte, $lt, $lte, $in, $nin, $ne, $regex, $or. Combine them on a single field (created_at={"$gte":"2026-01-01T00:00:00Z","$lt":"2026-02-01T00:00:00Z"}) or across fields (status=active&user_id=...).
Common queries
# Active + inactive + pending cards of a specific user (the dashboard's default)
GET /v1/vendor_cards?\
$or=[{"status":"active"},{"status":"inactive"},{"status":"pending"}]&\
user_id=<firebase_uid>&\
_order=desc&_field=created_at&_start=0&_end=25
# Search by name OR last4 (cardholder lookup)
GET /v1/vendor_cards?\
$or=[{"name":{"$regex":"maria"}},{"last4":{"$regex":"^4242"}}]&\
_start=0&_end=50
# Cards assigned to a specific person, with allocation-based control
GET /v1/vendor_cards?\
user_id=<firebase_uid>&\
spending_control_strategy=allocation_based
# Cards by id (batch lookup, e.g. to refresh a dashboard view)
GET /v1/vendor_cards?id={"$in":["Q2FyZDoxMDIwNjQ5Mw==","Q2FyZDoxMDIwNjQ5NA=="]}| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
401Unauthorized — missing or invalid bearer token, or the caller is not
permitted to list vendor cards (Pundit authorization failure). Returned
with an empty body. Note: the company-id header is not required for
this endpoint.
