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

# Create Webhook Endpoint

> Register a new webhook endpoint to receive asynchronous payment notifications

<Note>
  This endpoint requires HMAC-SHA256 authentication. See [Authentication](../../docs/terminal-gateway/authentication) for signature computation details.
</Note>

## Endpoint Validation

When you create a webhook endpoint, the system sends a validation ping to verify that the URL is publicly accessible. The endpoint must:

1. Use HTTPS protocol
2. Be publicly reachable from the internet
3. Respond with a `2xx` status code to the ping request

<Warning>
  If the validation ping fails, the endpoint will not be created. Ensure your URL is accessible before attempting to register it.
</Warning>

## Endpoint Limits

Each group can configure up to **16 webhook endpoints**. Attempting to create more will return an `ENDPOINT_LIMIT_REACHED` error.

## Signing Secret

The response includes a `secret` field that is used to verify webhook signatures. This secret is **only returned once** during endpoint creation.

<Tip>
  Store the webhook signing secret securely. You'll need it to verify incoming webhook payloads. See [Receiving Webhooks](../../docs/terminal-gateway/http/webhooks-receiving) for signature verification details.
</Tip>

## Event Types

Subscribe to one or more event types:

| Event               | Description                                  |
| ------------------- | -------------------------------------------- |
| `payment.completed` | Payment succeeded on the terminal            |
| `payment.failed`    | Payment was declined or encountered an error |
| `payment.cancelled` | User cancelled the payment                   |
| `payment.timeout`   | Terminal didn't respond within 90 seconds    |


## OpenAPI

````yaml api-reference/terminal-gateway/openapi.json POST /v1/webhooks/endpoints
openapi: 3.1.0
info:
  title: Terminal Gateway HTTP API
  version: 1.0.0
  description: >-
    HTTP API for POS-to-terminal communication. Enables payment processing
    through connected terminals.
  contact:
    name: Modulus Labs Support
    email: support@moduluslabs.io
servers:
  - url: https://your-endpoint.moduluslabs.io
    description: >-
      Your provisioned Terminal Gateway API endpoint. Contact
      support@moduluslabs.io to obtain your URL and credentials.
security:
  - hmacAuth: []
tags:
  - name: Terminals
    description: Terminal discovery and management
  - name: Payments
    description: Payment processing
  - name: Transactions
    description: Transaction status and reconciliation
  - name: Webhooks
    description: Webhook endpoint management for asynchronous payment notifications
paths:
  /v1/webhooks/endpoints:
    post:
      tags:
        - Webhooks
      summary: Create Webhook Endpoint
      description: >-
        Register a new webhook endpoint to receive payment notifications. The
        endpoint URL must be publicly accessible and use HTTPS. A validation
        ping is sent to verify connectivity before the endpoint is created.
      operationId: createWebhookEndpoint
      requestBody:
        required: true
        description: Webhook endpoint configuration
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWebhookEndpointRequest'
            example:
              url: https://api.yourcompany.com/webhooks/payments
              events:
                - payment.completed
                - payment.failed
                - payment.cancelled
                - payment.timeout
              description: Production payment notifications
              metadata:
                environment: production
      responses:
        '201':
          description: Webhook endpoint created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEndpointResponse'
              example:
                endpointId: wh_01HQ3K4M5N6P7R8S9T0UVWXYZ
                url: https://api.yourcompany.com/webhooks/payments
                events:
                  - payment.completed
                  - payment.failed
                  - payment.cancelled
                  - payment.timeout
                description: Production payment notifications
                secret: whsec_abc123xyz789...
                status: active
                metadata:
                  environment: production
                createdAt: '2024-01-15T10:30:00.000Z'
                updatedAt: '2024-01-15T10:30:00.000Z'
        '400':
          $ref: '#/components/responses/WebhookBadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    CreateWebhookEndpointRequest:
      type: object
      required:
        - url
        - events
      properties:
        url:
          type: string
          format: uri
          description: >-
            The HTTPS URL where webhook payloads will be delivered. Must be
            publicly accessible.
        events:
          type: array
          items:
            type: string
            enum:
              - payment.completed
              - payment.failed
              - payment.cancelled
              - payment.timeout
          description: Array of event types to subscribe to.
        description:
          type: string
          description: Human-readable description for this endpoint.
        metadata:
          type: object
          description: Custom key-value pairs to associate with this endpoint.
          additionalProperties: true
    WebhookEndpointResponse:
      type: object
      required:
        - endpointId
        - url
        - events
        - secret
        - status
        - createdAt
        - updatedAt
      properties:
        endpointId:
          type: string
          description: Unique identifier for the webhook endpoint.
        url:
          type: string
          format: uri
          description: The HTTPS URL where webhook payloads are delivered.
        events:
          type: array
          items:
            type: string
            enum:
              - payment.completed
              - payment.failed
              - payment.cancelled
              - payment.timeout
          description: Event types this endpoint is subscribed to.
        description:
          type: string
          description: Human-readable description for this endpoint.
        secret:
          type: string
          description: >-
            Webhook signing secret. Only returned on endpoint creation. Store
            securely for signature verification.
        status:
          type: string
          enum:
            - active
            - disabled
          description: Endpoint status.
        metadata:
          type: object
          description: Custom key-value pairs associated with this endpoint.
          additionalProperties: true
        createdAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp of when the endpoint was created.
        updatedAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp of the last update.
    Error:
      type: object
      required:
        - error
        - timestamp
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Error code
            message:
              type: string
              description: Human-readable error message
            details:
              type: object
              description: Additional error details
              additionalProperties: true
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp
        requestId:
          type: string
          description: Request identifier for debugging
        transactionId:
          type: string
          description: Transaction ID if applicable
  responses:
    WebhookBadRequest:
      description: Invalid webhook request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            webhooksNotConfigured:
              summary: Webhooks not configured
              value:
                error:
                  code: WEBHOOKS_NOT_CONFIGURED
                  message: Webhooks feature is not enabled for your group
                timestamp: '2024-01-15T10:40:00.000Z'
            endpointLimitReached:
              summary: Endpoint limit reached
              value:
                error:
                  code: ENDPOINT_LIMIT_REACHED
                  message: Maximum of 16 webhook endpoints per group reached
                timestamp: '2024-01-15T10:40:00.000Z'
            invalidEndpointUrl:
              summary: Invalid endpoint URL
              value:
                error:
                  code: INVALID_ENDPOINT_URL
                  message: URL must use HTTPS protocol
                timestamp: '2024-01-15T10:40:00.000Z'
            endpointPingFailed:
              summary: Endpoint ping failed
              value:
                error:
                  code: ENDPOINT_PING_FAILED
                  message: >-
                    Validation ping to endpoint URL failed. Ensure the URL is
                    publicly accessible.
                timestamp: '2024-01-15T10:40:00.000Z'
            invalidEventType:
              summary: Invalid event type
              value:
                error:
                  code: INVALID_EVENT_TYPE
                  message: Unknown event type in events array
                timestamp: '2024-01-15T10:40:00.000Z'
    Unauthorized:
      description: Authentication failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            unauthorized:
              summary: Invalid API key
              value:
                error:
                  code: UNAUTHORIZED
                  message: Missing or invalid API key
                timestamp: '2024-01-15T10:40:00.000Z'
            invalidSignature:
              summary: Invalid signature
              value:
                error:
                  code: INVALID_SIGNATURE
                  message: HMAC signature verification failed
                timestamp: '2024-01-15T10:40:00.000Z'
            timestampExpired:
              summary: Timestamp expired
              value:
                error:
                  code: TIMESTAMP_EXPIRED
                  message: Request timestamp outside 5-minute window
                timestamp: '2024-01-15T10:40:00.000Z'
    Forbidden:
      description: Access denied
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: GROUP_MISMATCH
              message: Resource belongs to a different group
            timestamp: '2024-01-15T10:40:00.000Z'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INTERNAL_ERROR
              message: Unexpected server error
            timestamp: '2024-01-15T10:40:00.000Z'
  securitySchemes:
    hmacAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        HMAC-SHA256 authentication. Requires three headers: x-api-key (your API
        key), x-timestamp (ISO 8601 timestamp), and x-signature (Base64-encoded
        HMAC-SHA256 signature). See Authentication documentation for signature
        computation.

````