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

# Receive a provider webhook

> Accepts a settlement event pushed by the payment provider, persists it verbatim and returns 202 only after that persistence succeeds. This route is served only by a single-tenant deployment; a multi-tenant deployment serves the per-connection route at this path plus a connection token instead, and this document advertises both because it is generated without a deployment mode. If the deployment's storage is unavailable the event is not persisted and the response is 503 (retryable) instead of 202. Authentication is an HMAC-SHA256 signature over the raw request body, sent as lowercase hex in x-webhook-baas-signature and computed with a secret agreed with the provider, not the platform identity used by the rest of this API. The body is the provider envelope: pactualId, entity and status are required, clientRequestId and createTimestamp are optional, and any further member is accepted and stored as sent. Member names are matched without regard to case. The x-webhook-baas-entity and x-webhook-baas-event headers are optional copies of entity and status; where a header disagrees with the body the body is authoritative, because only the body is signed. The x-webhook-baas-notifyid header identifies the logical notification and, when sent, is what this endpoint deduplicates on; a delivery without it is still accepted and deduplicated on a key derived from pactualId, entity, status and createTimestamp. The x-webhook-baas-deliveryid header names one attempt to deliver that notification rather than the notification itself; it is optional, it decides nothing, and it is recorded only in this endpoint's logs, so that a delivery can be matched against the provider's own list of failed attempts. A delivery whose status names a provider TRANSPORT event rather than a business one — PING, which the provider's own webhook test emits and which belongs to no entity's event catalogue — is the single exception to all of the above: it is answered 202 without being deduplicated and without being persisted.



## OpenAPI

````yaml /pt/openapi/v3-current/payments.yaml post /v1/webhooks/btg
openapi: 3.1.0
info:
  description: >-
    API for the Lerian Payments interface via BTG. It covers boleto issuance,
    cancellation, and queries; bill payments (bankslip, utilities, and DARF) and
    queries; aggregated boleto and payment dashboards; provider connection and
    outbound webhook configuration; and the provider webhook receiver for
    settlement events.


    ERROR BODIES. A failed request arrives as an RFC 9457 problem document on
    application/problem+json. Branch on the code member. A license refusal
    carries an LCS code, listed in the License Manager error list.
  title: Payments — via BTG API
  version: 1.0.0
servers:
  - url: https://api.example.com
    description: >-
      Replace the example host with the URL provided during environment
      onboarding.
security: []
tags:
  - description: >-
      Tenant-level setup: connecting the banking provider and configuring where
      status notifications are delivered.
    name: Admin
  - description: Issuing, querying and cancelling boletos, and retrieving the rendered PDF.
    name: Boletos
  - description: >-
      Aggregated counts, amounts and breakdowns over a period, for boletos and
      for payments.
    name: Dashboards
  - description: >-
      Paying bankslips, utility bills and DARF tax slips, and querying those
      payments.
    name: Payments
  - description: >-
      The webhook the payment provider posts settlement events to. Authenticated
      with a credential agreed with the provider, not with the platform identity
      used by the rest of this API.
    name: Settlement
paths:
  /v1/webhooks/btg:
    post:
      tags:
        - Settlement
      summary: Receive a provider webhook
      description: >-
        Accepts a settlement event pushed by the payment provider, persists it
        verbatim and returns 202 only after that persistence succeeds. This
        route is served only by a single-tenant deployment; a multi-tenant
        deployment serves the per-connection route at this path plus a
        connection token instead, and this document advertises both because it
        is generated without a deployment mode. If the deployment's storage is
        unavailable the event is not persisted and the response is 503
        (retryable) instead of 202. Authentication is an HMAC-SHA256 signature
        over the raw request body, sent as lowercase hex in
        x-webhook-baas-signature and computed with a secret agreed with the
        provider, not the platform identity used by the rest of this API. The
        body is the provider envelope: pactualId, entity and status are
        required, clientRequestId and createTimestamp are optional, and any
        further member is accepted and stored as sent. Member names are matched
        without regard to case. The x-webhook-baas-entity and
        x-webhook-baas-event headers are optional copies of entity and status;
        where a header disagrees with the body the body is authoritative,
        because only the body is signed. The x-webhook-baas-notifyid header
        identifies the logical notification and, when sent, is what this
        endpoint deduplicates on; a delivery without it is still accepted and
        deduplicated on a key derived from pactualId, entity, status and
        createTimestamp. The x-webhook-baas-deliveryid header names one attempt
        to deliver that notification rather than the notification itself; it is
        optional, it decides nothing, and it is recorded only in this endpoint's
        logs, so that a delivery can be matched against the provider's own list
        of failed attempts. A delivery whose status names a provider TRANSPORT
        event rather than a business one — PING, which the provider's own
        webhook test emits and which belongs to no entity's event catalogue — is
        the single exception to all of the above: it is answered 202 without
        being deduplicated and without being persisted.
      operationId: receiveProviderWebhook
      parameters:
        - description: >-
            HMAC-SHA256 of the raw request body, lowercase hex. WHICH key signs
            it depends on the route: the unparameterised route verifies against
            the deployment-wide provider secret, while the per-connection route
            verifies against the signing key issued for that connection_token
            and nothing else — a delivery signed with the deployment-wide secret
            is refused there. It is verified by a per-operation middleware that
            runs before any schema check, so a request that omits it, or carries
            a value that does not match the body, is refused with 401 PBP-0500
            and never with a schema error.
          in: header
          name: x-webhook-baas-signature
          required: true
          schema:
            description: >-
              HMAC-SHA256 of the raw request body, lowercase hex. WHICH key
              signs it depends on the route: the unparameterised route verifies
              against the deployment-wide provider secret, while the
              per-connection route verifies against the signing key issued for
              that connection_token and nothing else — a delivery signed with
              the deployment-wide secret is refused there. It is verified by a
              per-operation middleware that runs before any schema check, so a
              request that omits it, or carries a value that does not match the
              body, is refused with 401 PBP-0500 and never with a schema error.
            type: string
        - description: >-
            Provider entity name, repeating the body's entity member.
            Cross-checked against it; the body decides, because only the body is
            under the signature.
          in: header
          name: x-webhook-baas-entity
          schema:
            description: >-
              Provider entity name, repeating the body's entity member.
              Cross-checked against it; the body decides, because only the body
              is under the signature.
            type: string
        - description: >-
            Provider event name, which is the same value as the body's status
            member. Cross-checked against it; the body decides.
          in: header
          name: x-webhook-baas-event
          schema:
            description: >-
              Provider event name, which is the same value as the body's status
              member. Cross-checked against it; the body decides.
            type: string
        - description: >-
            Provider identifier of the LOGICAL notification, as opposed to one
            delivery attempt of it. When present it becomes this delivery's
            deduplication key; when absent the key is derived from the envelope
            instead, and the delivery is still accepted.
          in: header
          name: x-webhook-baas-notifyid
          schema:
            description: >-
              Provider identifier of the LOGICAL notification, as opposed to one
              delivery attempt of it. When present it becomes this delivery's
              deduplication key; when absent the key is derived from the
              envelope instead, and the delivery is still accepted.
            type: string
        - description: >-
            Provider identifier of ONE ATTEMPT to deliver a notification, as
            opposed to the notification itself. It decides nothing: it is never
            deduplicated on and no column holds it, because an attempt
            identifier is fresh on every retry. It is recorded in this
            endpoint's logs so a delivery can be matched against the provider's
            own list of failed attempts. A delivery without it is still
            accepted.
          in: header
          name: x-webhook-baas-deliveryid
          schema:
            description: >-
              Provider identifier of ONE ATTEMPT to deliver a notification, as
              opposed to the notification itself. It decides nothing: it is
              never deduplicated on and no column holds it, because an attempt
              identifier is fresh on every retry. It is recorded in this
              endpoint's logs so a delivery can be matched against the
              provider's own list of failed attempts. A delivery without it is
              still accepted.
            type: string
        - description: >-
            Optional provider correlation identifier. Persisted with the event
            when present.
          in: header
          name: X-Correlation-Id
          schema:
            description: >-
              Optional provider correlation identifier. Persisted with the event
              when present.
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProviderWebhookPayload'
        required: true
      responses:
        '202':
          description: Accepted
        '400':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Bad Request
        '401':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Unauthorized
        '413':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Request Entity Too Large
        '415':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Unsupported Media Type
        '422':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Unprocessable Entity
        '500':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Internal Server Error
        '503':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Service Unavailable
components:
  schemas:
    ProviderWebhookPayload:
      additionalProperties: true
      properties:
        clientRequestId:
          description: >-
            Identifier this service sent when it created the entity, echoed back
            for correlation. Optional here even though the provider envelope
            declares it required.
          type: string
        createTimestamp:
          description: >-
            Instant the provider recorded for this state, RFC 3339. Optional
            here: a delivery without one means no reference instant, not a
            malformed request.
          format: date-time
          type: string
        entity:
          description: >-
            Provider entity name the event belongs to, for example
            PaymentSlipPay or TaxDarfPayment. Cross-checked against
            x-webhook-baas-entity; the body wins.
          type: string
        pactualId:
          description: >-
            Provider-assigned primary key of the entity this event is about. A
            string representation of a GUID in every delivery seen so far, but
            not validated as one: the field is the provider's to shape.
          type: string
        status:
          description: >-
            Provider state the entity moved to, for example PAID. This IS the
            provider's event name — the x-webhook-baas-event header carries the
            same value — and it is stored as sent.
          type: string
      required:
        - pactualId
        - entity
        - status
      type: object
    Detail:
      additionalProperties: true
      properties:
        code:
          description: >-
            Stable, machine-readable domain error code scoped to the emitting
            service (format: <SERVICE>-NNNN).
          type: string
        detail:
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem.
          examples:
            - Property foo is required but is missing.
          type: string
        errors:
          description: Optional list of individual error details
          items:
            $ref: '#/components/schemas/ErrorDetail'
          type:
            - array
            - 'null'
        instance:
          description: >-
            A URI reference that identifies the specific occurrence of the
            problem.
          examples:
            - https://example.com/error-log/abc123
          format: uri
          type: string
        status:
          description: HTTP status code
          examples:
            - 400
          format: int64
          type: integer
        title:
          description: >-
            A short, human-readable summary of the problem type. This value
            should not change between occurrences of the error.
          examples:
            - Bad Request
          type: string
        type:
          default: about:blank
          description: A URI reference to human-readable documentation for the error.
          examples:
            - https://example.com/errors/example
          format: uri
          type: string
        upstream:
          $ref: '#/components/schemas/Upstream'
          description: >-
            RFC 9457 extension member: the error a proxied third-party provider
            reported. Absent unless the emitting service explicitly surfaced
            one.
      type: object
    ErrorDetail:
      additionalProperties: false
      properties:
        location:
          description: >-
            Where the error occurred, e.g. 'body.items[3].tags' or
            'path.thing-id'
          type: string
        message:
          description: Error message text
          type: string
        value:
          description: The value at the given location
      type: object
    Upstream:
      additionalProperties: false
      properties:
        code:
          description: The upstream provider's own error code, verbatim.
          examples:
            - E4001
          type: string
        message:
          description: >-
            The upstream provider's own error message, verbatim (bounded, never
            its raw response body).
          examples:
            - account not found at provider
          type: string
      type: object

````

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