> ## Documentation Index
> Fetch the complete documentation index at: https://vexioncards.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# List locations

> Lists your locations, newest first - each row is the **full Location object**: address + pin, geo notification, enabled cards with their per-location signup URLs, assigned team, and POS-bridge status. Organizations have few locations, so no slim row shape exists; one call gives you everything the dashboard's location screen shows. Scope: `locations:read`.

Locations are created and deleted **in the dashboard only** - each location is a billing unit, so lifecycle changes go through the billing consent flow there. The API reads and edits.

See [Pagination](/api-reference/pagination).



## OpenAPI

````yaml /openapi.json get /v1/locations
openapi: 3.1.0
info:
  title: VEXiON cards Public API
  description: >-
    ## Rate limiting


    Two independent layers, checked in this order:


    1. **Per-IP throttle (pre-authentication).** Applied to every `/v1` request
    BEFORE the API key is checked, keyed on the caller's IP address:
       - **600 requests/minute** per IP - a flood ceiling, `429 rate_limit_error` / `rate_limited`.
       - **20 failed authentications per 15 minutes** per IP - a key-guessing ceiling. Only responses that are `401` (missing/invalid/revoked key) count against this ceiling; a `403` from a valid key that simply lacks a scope does not. `429 rate_limit_error` / `too_many_failed_attempts`.

       Both ceilings send `Retry-After` (seconds).
    2. **Per-key, per-bucket limiter (post-authentication).** Documented per
    endpoint (see each operation's `429` response and the `rate_limit` field on
    the API Key resource) - e.g. 60/min default, 120/min for transactions, plus
    the notification-broadcast and lookup-filter buckets described on their own
    endpoints.


    ### Rate-limit response headers


    Every rate-limited response carries the legacy `X-RateLimit-Limit` /
    `X-RateLimit-Remaining` / `X-RateLimit-Reset` family (the last is an **epoch
    timestamp**) AND the IETF standards-track headers, side by side:


    - `RateLimit-Policy: "<bucket>";q=<quota>;w=<window seconds>` - the static
    policy for the bucket that was hit.

    - `RateLimit: "<bucket>";r=<remaining>;t=<seconds until reset>` - live
    state. **`t` is a DURATION (seconds remaining), not the epoch timestamp
    `X-RateLimit-Reset` carries - the two are never the same value.**
  version: 1.0.0
servers:
  - url: https://api.vexioncards.one
    description: Production
  - url: https://migration.api.vexioncards.one
    description: Sandbox
security:
  - apiKey: []
tags:
  - name: Customers
  - name: Cards
  - name: Transactions
  - name: Notifications
  - name: Locations
  - name: Products
  - name: API keys
  - name: Organization
  - name: Webhook endpoints
  - name: Events
  - name: Custom fields
  - name: Team members
  - name: Icons
paths:
  /v1/locations:
    get:
      tags:
        - Locations
      summary: List locations
      description: >-
        Lists your locations, newest first - each row is the **full Location
        object**: address + pin, geo notification, enabled cards with their
        per-location signup URLs, assigned team, and POS-bridge status.
        Organizations have few locations, so no slim row shape exists; one call
        gives you everything the dashboard's location screen shows. Scope:
        `locations:read`.


        Locations are created and deleted **in the dashboard only** - each
        location is a billing unit, so lifecycle changes go through the billing
        consent flow there. The API reads and edits.


        See [Pagination](/api-reference/pagination).
      operationId: listLocations
      parameters:
        - name: limit
          in: query
          description: 1-100. Default 25.
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 25
        - name: starting_after
          in: query
          required: false
          description: >-
            Cursor - the `loc_` id of the last item on the previous page
            (forward). Numeric offset or page parameters are not supported;
            cursors are the only supported paging mechanism.
          schema:
            type: string
            pattern: ^loc_[A-Za-z0-9]+$
          example: loc_01HW9R9Z4EF7N8MTX1RVLOCDEF
        - name: ending_before
          in: query
          required: false
          description: Reverse cursor - returns items before this `loc_` id.
          schema:
            type: string
            pattern: ^loc_[A-Za-z0-9]+$
      responses:
        '200':
          description: Paginated location list.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LocationList'
              examples:
                Two stores:
                  summary: POS-bridged flagship + a second store
                  value:
                    object: list
                    data:
                      - id: loc_01HW9R4P2ZK7N8MTX1RVLOCS01
                        object: location
                        name: Demo Coffee - City Center
                        address: Hlavná 12, 811 01 Bratislava, Slovakia
                        coordinates:
                          latitude: 48.1486
                          longitude: 17.1077
                        country: SK
                        geo_message: >-
                          You're near Demo Coffee - your 10th coffee is on us
                          today! ☕
                        geo_message_enabled: true
                        enabled_card_ids:
                          - crd_56gd3jpqoipsfjoa7cjabfqope
                          - crd_2hh2fekk5zazfyyvian4uhepyq
                        cards:
                          - card_id: crd_56gd3jpqoipsfjoa7cjabfqope
                            name: Coffee Stamp Card
                            type: stamp
                            signup_url: >-
                              https://vexioncards.one/signup/?id=crd_56gd3jpqoipsfjoa7cjabfqope&loc=loc_01HW9R4P2ZK7N8MTX1RVLOCS01
                          - card_id: crd_2hh2fekk5zazfyyvian4uhepyq
                            name: Coffee Points
                            type: reward
                            signup_url: >-
                              https://vexioncards.one/signup/?id=crd_2hh2fekk5zazfyyvian4uhepyq&loc=loc_01HW9R4P2ZK7N8MTX1RVLOCS01
                        team_members:
                          - team_member_id: tm_01HW9R6M4XQ2N8MTX1RVTM0001
                            name: Anna K.
                            role: scanner
                          - team_member_id: tm_01HW9R6M4XQ2N8MTX1RVTM0002
                            name: Peter V.
                            role: manager
                        pos_connected: true
                        is_default: true
                        is_active: true
                        created_at: 1735689600
                        updated_at: 1751500000
                      - id: loc_01HW9R4P2ZK7N8MTX1RVLOCS02
                        object: location
                        name: Demo Coffee - Riverside
                        address: Nábrežná 3, 811 02 Bratislava, Slovakia
                        coordinates:
                          latitude: 48.1411
                          longitude: 17.1093
                        country: SK
                        geo_message: null
                        geo_message_enabled: false
                        enabled_card_ids:
                          - crd_56gd3jpqoipsfjoa7cjabfqope
                        cards:
                          - card_id: crd_56gd3jpqoipsfjoa7cjabfqope
                            name: Coffee Stamp Card
                            type: stamp
                            signup_url: >-
                              https://vexioncards.one/signup/?id=crd_56gd3jpqoipsfjoa7cjabfqope&loc=loc_01HW9R4P2ZK7N8MTX1RVLOCS01
                        team_members: []
                        pos_connected: false
                        is_default: false
                        is_active: true
                        created_at: 1735689600
                        updated_at: 1751500000
                    has_more: false
                    url: /v1/locations
                Single location:
                  summary: Typical single-store org
                  value:
                    object: list
                    data:
                      - id: loc_01HW9R4P2ZK7N8MTX1RVLOCS01
                        object: location
                        name: Demo Coffee - City Center
                        address: Hlavná 12, 811 01 Bratislava, Slovakia
                        coordinates:
                          latitude: 48.1486
                          longitude: 17.1077
                        country: SK
                        geo_message: >-
                          You're near Demo Coffee - your 10th coffee is on us
                          today! ☕
                        geo_message_enabled: true
                        enabled_card_ids:
                          - crd_56gd3jpqoipsfjoa7cjabfqope
                          - crd_2hh2fekk5zazfyyvian4uhepyq
                        cards:
                          - card_id: crd_56gd3jpqoipsfjoa7cjabfqope
                            name: Coffee Stamp Card
                            type: stamp
                            signup_url: >-
                              https://vexioncards.one/signup/?id=crd_56gd3jpqoipsfjoa7cjabfqope&loc=loc_01HW9R4P2ZK7N8MTX1RVLOCS01
                          - card_id: crd_2hh2fekk5zazfyyvian4uhepyq
                            name: Coffee Points
                            type: reward
                            signup_url: >-
                              https://vexioncards.one/signup/?id=crd_2hh2fekk5zazfyyvian4uhepyq&loc=loc_01HW9R4P2ZK7N8MTX1RVLOCS01
                        team_members:
                          - team_member_id: tm_01HW9R6M4XQ2N8MTX1RVTM0001
                            name: Anna K.
                            role: scanner
                          - team_member_id: tm_01HW9R6M4XQ2N8MTX1RVTM0002
                            name: Peter V.
                            role: manager
                        pos_connected: true
                        is_default: true
                        is_active: true
                        created_at: 1735689600
                        updated_at: 1751500000
                    has_more: false
                    url: /v1/locations
          headers: {}
        '400':
          description: Malformed body or missing required field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers: {}
        '401':
          description: Missing, invalid, or revoked API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers: {}
        '403':
          description: API key lacks the required scope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers: {}
        '429':
          description: Per-minute or per-day rate limit exceeded. Respect Retry-After.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers: {}
        '500':
          description: Server error. Retry-safe on idempotent calls.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers: {}
      deprecated: false
components:
  schemas:
    LocationList:
      allOf:
        - $ref: '#/components/schemas/ListResponse'
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/Location'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - type
            - code
            - message
          properties:
            type:
              type: string
              enum:
                - invalid_request_error
                - authentication_error
                - permission_error
                - not_found_error
                - rate_limit_error
                - idempotency_error
                - api_error
            code:
              type: string
            message:
              type: string
            retry_after:
              type: integer
              description: >-
                Seconds to wait before retrying. Present on rate-limit (429) and
                idempotency-key-in-use (409) errors; mirrors the `Retry-After`
                HTTP header. Absent on error types that carry no retry guidance.
              example: 5
            param:
              type:
                - string
                - 'null'
            request_id:
              type: string
            doc_url:
              type: string
              format: uri
            field_errors:
              type: array
              description: >-
                Per-field errors on a 422. At most 100 entries: a request with
                more errors gets the first 100.
              items:
                type: object
                properties:
                  param:
                    type: string
                  code:
                    type: string
                  message:
                    type: string
                  expected_currency:
                    type: string
                    description: >-
                      On `currency_mismatch`: the business currency the request
                      must use. Absent on every other field error.
          description: >-
            The error payload: type (category), code (machine-readable), message
            (human-readable), retry_after (seconds, on
            rate-limit/idempotency-in-use errors only), param (offending field),
            request_id, doc_url, field_errors[].
      description: >-
        Standard error envelope. Branch on `error.code`; include
        `error.request_id` in support requests. See the Errors guide.
    ListResponse:
      type: object
      required:
        - object
        - data
        - has_more
      properties:
        object:
          type: string
          enum:
            - list
          description: Always `"list"`.
        data:
          type: array
          items: {}
          description: Array of the requested resource type.
        has_more:
          type: boolean
          description: True when more pages exist.
        next_cursor:
          type:
            - string
            - 'null'
          description: >-
            Cursor for the next page **in the direction you are already
            paging**, or `null` when this page ends the collection. `has_more:
            true` always comes with a non-null `next_cursor`.


            Feed it back to the SAME parameter you used: `starting_after` when
            paging forward (the default), or `ending_before` when paging
            backward. Treat it as opaque and do not parse it.


            You no longer need to take the last object's `id` yourself. That
            still works and is unchanged, but deriving the cursor from the page
            put the burden of knowing the sort direction on you, and it broke
            silently on any endpoint whose cursor is not the object id.
          example: cus_iofv5j4hn6bphinmmyat27tc5y
        url:
          type: string
          description: Stable collection URL.
      description: >-
        Standard cursor-pagination envelope - see
        [Pagination](/api-reference/pagination).
    Location:
      type: object
      description: >-
        A physical store - the unit of POS bridging, team assignment, geo
        notifications, and per-location card availability. Locations are
        **created and deleted in the dashboard only** (each is a billing unit);
        the API reads and edits them.
      required:
        - id
        - object
        - name
        - address
        - coordinates
        - geo_message_enabled
        - enabled_card_ids
        - cards
        - team_members
        - pos_connected
        - is_default
        - is_active
        - created_at
      properties:
        id:
          type: string
          pattern: ^loc_[A-Za-z0-9]+$
          description: Location identifier, `loc_` prefix.
          example: loc_01HW9R4P2ZK7N8MTX1RVLOCS01
        object:
          type: string
          const: location
          description: Always `"location"`.
        name:
          type: string
          minLength: 1
          maxLength: 60
          description: >-
            Display name shown in the dashboard, scanner, and transaction
            attribution.
          example: Demo Coffee - City Center
        address:
          type:
            - string
            - 'null'
          description: >-
            Human-readable street address, one line. Writable - see PATCH for
            the address ↔ coordinates interplay (sending a new address alone
            re-geocodes the pin server-side).
          example: Hlavná 12, 811 01 Bratislava, Slovakia
        coordinates:
          type:
            - object
            - 'null'
          description: >-
            The pin - drives the wallet-pass geofence and map display. Kept in
            sync with `address` by geocoding, or set directly to fine-tune (the
            API equivalent of dragging the map pin).
          required:
            - latitude
            - longitude
          properties:
            latitude:
              type: number
              minimum: -90
              maximum: 90
              description: WGS84 latitude.
              example: 48.1486
            longitude:
              type: number
              minimum: -180
              maximum: 180
              description: WGS84 longitude.
              example: 17.1077
          example:
            latitude: 48.1486
            longitude: 17.1077
        country:
          type:
            - string
            - 'null'
          description: >-
            ISO 3166-1 alpha-2, derived from the geocoded address. Null while no
            address is set.
          example: SK
        geo_message:
          type:
            - string
            - 'null'
          maxLength: 500
          description: >-
            The push text shown on the customer's lock screen when they come
            near this location (wallet-pass geofencing; the trigger radius is
            fixed by Apple/Google at roughly 100 m - not configurable). Null =
            no message configured. Only fires while `geo_message_enabled` is
            true.
          example: You're near Demo Coffee - your 10th coffee is on us today! ☕
        geo_message_enabled:
          type: boolean
          description: >-
            Master switch for the geo notification at this location. The message
            text is kept when you toggle off.
          example: true
        enabled_card_ids:
          type: array
          items:
            type: string
            pattern: ^crd_[A-Za-z0-9]+$
          description: >-
            Which card templates are active at this location - the writable
            source of truth behind `cards[]`. PATCH with SET semantics to toggle
            cards on/off. Enabling a card also pushes this location's geofence
            onto that card's wallet passes (Apple Wallet caps geofences at 10
            locations per pass).
          example:
            - crd_56gd3jpqoipsfjoa7cjabfqope
            - crd_2hh2fekk5zazfyyvian4uhepyq
        cards:
          type: array
          description: >-
            Read-only expansion of `enabled_card_ids` - **only the cards turned
            ON at this location**, each with its per-(card, location)
            `signup_url`. The URL is long-lived and never rotates: render your
            own QR from it for counter cards and window decals. Customers who
            sign up through it get this location stamped as
            `Customer.signup_location_id`. Distinct from the per-customer
            `claim_url` (wallet handoff).


            Deliberately NOT the full org catalog with on/off flags: embedding
            every card template in every location response would bloat list
            calls and go stale as templates are added. To build a toggle UI like
            the dashboard's, join two clean resources: `GET /v1/cards` (the full
            catalog) against this location's `enabled_card_ids` (the on/off
            state). To toggle, PATCH `enabled_card_ids` with the new SET.
          items:
            type: object
            required:
              - card_id
              - name
              - type
              - signup_url
            properties:
              card_id:
                type: string
                pattern: ^crd_[A-Za-z0-9]+$
                description: The enabled card template.
                example: crd_56gd3jpqoipsfjoa7cjabfqope
              name:
                type: string
                description: Card display name (default language).
                example: Coffee Stamp Card
              type:
                type: string
                enum:
                  - stamp
                  - reward
                  - discount
                  - coupon
                  - membership
                  - gift_card
                  - custom
                description: Card family.
                example: stamp
              signup_url:
                type: string
                format: uri
                description: Stable signup landing URL for this card at this location.
                example: >-
                  https://vexioncards.one/signup/?id=crd_56gd3jpqoipsfjoa7cjabfqope&loc=loc_01HW9R4P2ZK7N8MTX1RVLOCS01
        team_members:
          type: array
          description: >-
            Read-only summary of who is assigned here. The write path is `PATCH
            /v1/team_members/{id}` with `location_ids` - one relationship, one
            owner; this is the location-side read.
          items:
            type: object
            required:
              - team_member_id
              - role
            properties:
              team_member_id:
                type: string
                pattern: ^tm_[A-Za-z0-9]+$
                description: The assigned team member.
                example: tm_01HW9R6M4XQ2N8MTX1RVTM0001
              name:
                type:
                  - string
                  - 'null'
                description: Display name.
                example: Anna K.
              role:
                type: string
                enum:
                  - manager
                  - scanner
                description: >-
                  Their role at this location. Admins never appear here - they
                  have implicit access to all locations.
                example: scanner
        pos_connected:
          type: boolean
          description: >-
            True when this location has a live POS bridge - sales at the till
            flow in automatically as `source: "pos"` transactions. **Boolean by
            design:** the one integration decision this flag serves is "do I
            need to push transactions via the API, or does the till already
            report them?". The POS vendor, connection ids, and mapping details
            are internal (vendor privacy) and dashboard-owned - they are never
            surfaced or editable via API.
          example: true
        is_default:
          type: boolean
          description: >-
            The organization's default location (used when a write carries no
            explicit `location_id` and the org has exactly one candidate).
          example: true
        is_active:
          type: boolean
          description: >-
            Read-only lifecycle flag. Deactivating a location is a billing
            action - dashboard only.
          example: true
        created_at:
          type: integer
          description: Unix seconds.
          example: 1735689600
        updated_at:
          type: integer
          description: Unix seconds of last change.
          example: 1751500000
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        Your secret API key as a Bearer token: `Authorization: Bearer
        vxn_sk_...`. Keys are created and scoped in the dashboard - see
        [Authentication](/api-reference/introduction#authentication).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.