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

> ## Agent Instructions
> Documentação das APIs da DeliveryVip, em português. Regras que mais quebram integrações: (1) Merchant API: faça polling em GET /merchant/v3/events:polling no máximo a cada 30 s por token; confirme todo evento recebido com POST /merchant/v3/events/acknowledgment e corpo [{"id": "<eventId>"}] (o campo lido é id, não eventId), inclusive eventos repetidos ou que o sistema não trata; deduplique por eventId; o evento é só um aviso, busque o pedido na orderURL. (2) Tokens client_credentials valem 24 h e não têm refresh_token: peça outro ao receber 401. (3) Webhooks: valide a assinatura HMAC sobre o corpo bruto e responda 2xx rápido; o polling é a reconciliação. (4) Open Delivery: host od.deliveryvip.com.br, um client_secret por loja, datas em UTC. (5) Fidelidade: o operador implementa 5 rotas assinadas com HMAC e chama o config push; o estorno precisa ser idempotente. (6) Partner API: scope dv.partner. Não invente endpoints: use a referência gerada das specs OpenAPI.

# Account balance

> Balance read for the checkout surface. DeliveryVip caches the answer for 60 seconds per account. The request carries only the opaque account id — never the CPF. Unknown fields in the response are ignored (emitting extras such as expiresAt or metadata is safe). The optional redemptionLimits object pins per-customer boundaries that override the program's for this customer — it rides the same 60-second cache as the balance, so a change to a customer's rules takes up to a minute to reach checkout.



## OpenAPI

````yaml https://app.deliveryvip.com.br/swaggers/loyalty_operator.yaml get /v1/loyalty/accounts/{accountId}
openapi: 3.0.3
info:
  version: v1
  title: DeliveryVip Loyalty Operator Contract
  description: >-
    The HTTP contract a loyalty operator must implement to serve the DeliveryVip
    loyalty extension. DeliveryVip is the ordering application: it CALLS these
    endpoints on the api_base_url declared by the operator's app (loyalty
    extension, dv.loyalty scope). Every request is signed with HMAC-SHA256 of
    the RAW body (empty string for body-less requests) using the app's OAuth
    secret — verify the signature against the exact bytes received, never a
    re-serialization. Respond fast: DeliveryVip uses 3s connect / 5s read
    timeouts, and 5 transport failures (timeout/5xx) within 5 minutes open a
    circuit breaker for the whole extension. Business answers (409/422/403/404)
    never count as failures. Configuration is pushed the other way (operator ->
    DeliveryVip) via PUT/DELETE /merchant/v3/{merchantId}/loyalty/config — see
    the Merchant API swagger; the PUT triggers a synchronous signed GET
    /v1/loyalty/ping here before anything is stored. That push is also where an
    operator declares its commercial boundaries per order
    (capabilities.redemptionLimits: an optional min and max, each fixed BRL or
    percent of the redeemable base). DeliveryVip enforces them before calling
    this API, so the amount below always already respects whatever the operator
    declared. Canonical byte-pinned request/response examples live in the
    platform repository under test/fixtures/files/loyalty/.
servers:
  - url: '{api_base_url}'
    description: >-
      The base URL the operator declares on the loyalty extension (https only;
      may include a path prefix).
    variables:
      api_base_url:
        default: https://operator.example.com/dv/v1
security:
  - appId: []
    appMerchantId: []
    appSignature: []
tags:
  - name: Handshake
    description: Synchronous verification during the config push.
  - name: Accounts
    description: >-
      Customer identity and balance. The account id must be opaque and stable
      across relinks.
  - name: Redemptions
    description: Synchronous balance debit (checkout) and its explicit idempotent reversal.
paths:
  /v1/loyalty/accounts/{accountId}:
    get:
      tags:
        - Accounts
      summary: Account balance
      description: >-
        Balance read for the checkout surface. DeliveryVip caches the answer for
        60 seconds per account. The request carries only the opaque account id —
        never the CPF. Unknown fields in the response are ignored (emitting
        extras such as expiresAt or metadata is safe). The optional
        redemptionLimits object pins per-customer boundaries that override the
        program's for this customer — it rides the same 60-second cache as the
        balance, so a change to a customer's rules takes up to a minute to reach
        checkout.
      parameters:
        - in: path
          name: accountId
          required: true
          schema:
            type: string
          description: The opaque account id returned by accounts:link.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/account'
        '404':
          description: >-
            Account no longer exists on the operator side. DeliveryVip treats
            the customer as not linked anymore and offers the opt-in again
            (never counted as an outage).
components:
  schemas:
    account:
      type: object
      required:
        - id
        - programId
        - balanceType
        - balance
        - currency
      properties:
        id:
          type: string
          description: >-
            Opaque and STABLE — relinking the same customer must return the same
            id byte-for-byte.
        programId:
          type: string
        balanceType:
          type: string
          enum:
            - cashback
        balance:
          type: number
          description: Current balance in BRL. Read format-agnostically by DeliveryVip.
        currency:
          type: string
          default: BRL
        redemptionLimits:
          allOf:
            - $ref: '#/components/schemas/redemptionLimits'
          description: >-
            OPTIONAL per-customer boundaries. When present they REPLACE the
            program-level capabilities.redemptionLimits for this customer
            entirely — not field by field: declaring only max here means this
            customer has no minimum, whatever the program declares. Omit the
            object (or omit a bound inside it) to leave the customer under the
            program's own limits. Answer here ONLY when your rules genuinely
            vary per customer (a tier, a segment, an individual agreement) — a
            single rule for every customer belongs on the program's
            capabilities, not repeated on every account. Note that a limit
            reaching you inside a per-customer lookup is not by itself evidence
            that the limit is per-customer. Malformed values are ignored and the
            program's limits stand.
    redemptionLimits:
      type: object
      description: >-
        Optional commercial boundaries per order. Omit the object, or either
        bound, to declare no limit there — omit it, never send null. Percentages
        apply to the redeemable base: the order's items minus other cart
        discounts. Shipping and fees are never redeemable, so a percentage
        ceiling is computed over items, not over the order total.
      properties:
        min:
          $ref: '#/components/schemas/redemptionLimit'
        max:
          $ref: '#/components/schemas/redemptionLimit'
    redemptionLimit:
      type: object
      description: >-
        A single boundary: a fixed amount in BRL or a percentage of the
        redeemable base. A minimum never raises the redeemed amount — it only
        decides whether redeeming is possible at all. Same shape the operator
        uses to declare program-level limits in capabilities.redemptionLimits
        (see the Merchant API swagger).
      required:
        - type
        - value
      properties:
        type:
          type: string
          enum:
            - fixed
            - percent
        value:
          type: number
          description: Amount in BRL when type is fixed; 0-100 when type is percent.
  securitySchemes:
    appId:
      type: apiKey
      in: header
      name: X-App-Id
      description: The uid of the operator's OAuth application on DeliveryVip.
    appMerchantId:
      type: apiKey
      in: header
      name: X-App-MerchantId
      description: The UUID of the merchant (company) the call concerns.
    appSignature:
      type: apiKey
      in: header
      name: X-App-Signature
      description: >-
        Hex HMAC-SHA256 of the raw request body (empty string when there is no
        body), keyed with the app's OAuth secret. Verify against the exact bytes
        received.

````

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