{
  "openapi": "3.1.1",
  "info": {
    "title": "Stendly Merchant API",
    "description": "Public Merchant API contract. Authenticate with an Authorization: Bearer st_live_... API key.",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.stendly.com",
      "description": "Mainnet"
    },
    {
      "url": "https://api-devnet.stendly.com",
      "description": "Devnet"
    }
  ],
  "paths": {
    "/api/b2b/merchants/me": {
      "get": {
        "tags": [
          "B2B Dashboard"
        ],
        "operationId": "GetMerchantProfile",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantProfileResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Standardized API error envelope.",
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/b2b/merchants/stats": {
      "get": {
        "tags": [
          "B2B Dashboard"
        ],
        "operationId": "GetMerchantStats",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantStatsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/b2b/merchants/webhook": {
      "patch": {
        "tags": [
          "B2B Dashboard"
        ],
        "operationId": "UpdateMerchantWebhook",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "callbacks": {
          "merchantWebhook": {
            "{$request.body#/webhookUrl}": {
              "post": {
                "summary": "Receive payment intent event",
                "description": "Stendly sends this POST request to the merchant webhook URL configured with PATCH /api/b2b/merchants/webhook.",
                "parameters": [
                  {
                    "name": "X-Stendly-Signature",
                    "in": "header",
                    "description": "HMAC-SHA256 signature over timestamp + raw JSON payload. Format: t={unix_timestamp},v1={hex_digest}.",
                    "required": true,
                    "schema": {
                      "type": "string",
                      "example": "t=1714567890,v1=3f4c2d8a9b0e1f2a3c4d5e6f7081920a"
                    }
                  },
                  {
                    "name": "X-Stendly-Idempotency-Key",
                    "in": "header",
                    "description": "Unique delivery idempotency key for this webhook attempt.",
                    "required": true,
                    "schema": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                ],
                "requestBody": {
                  "content": {
                    "application/json": {
                      "schema": {
                        "description": "Outgoing webhook payload sent by Stendly to the merchant webhook URL.",
                        "$ref": "#/components/schemas/MerchantWebhookPayload"
                      },
                      "example": {
                        "event": "payment_intent.succeeded",
                        "data": {
                          "paymentIntentId": "8c8b2f6b-16b3-4761-a5f0-8b8c9c5f1a11",
                          "orderId": "order_1001",
                          "amountCents": 1299,
                          "expectedAmountCents": 1299,
                          "txSignature": "5S5kY8uJp9..."
                        }
                      }
                    }
                  },
                  "required": true
                },
                "responses": {
                  "2XX": {
                    "description": "Webhook accepted by merchant endpoint."
                  }
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/b2b/merchants/terminals": {
      "get": {
        "tags": [
          "B2B Dashboard"
        ],
        "operationId": "ListMerchantTerminals",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TerminalResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      },
      "post": {
        "tags": [
          "B2B Dashboard"
        ],
        "operationId": "CreateMerchantTerminal",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTerminalRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TerminalResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/merchants/intents": {
      "post": {
        "tags": [
          "Merchants"
        ],
        "operationId": "CreatePaymentIntent",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "UUID used to make intent creation safe to retry. SDKs generate one automatically.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentIntentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentIntentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    },
    "/api/merchants/intents/{intentId}": {
      "get": {
        "tags": [
          "Merchants"
        ],
        "operationId": "GetPaymentIntent",
        "parameters": [
          {
            "name": "intentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentIntentResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          { }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "ApiError": {
        "type": "object",
        "properties": {
          "code": {
            "type": [
              "null",
              "string"
            ]
          },
          "message": {
            "type": [
              "null",
              "string"
            ]
          },
          "traceId": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "additionalProperties": false
      },
      "ApiErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ApiError"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API error envelope."
      },
      "CreatePaymentIntentRequest": {
        "required": [
          "orderId"
        ],
        "type": "object",
        "properties": {
          "amountCents": {
            "maximum": 9.223372036854776E+18,
            "minimum": 1,
            "type": "integer",
            "format": "int64"
          },
          "orderId": {
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          },
          "terminalId": {
            "type": [
              "null",
              "string"
            ],
            "format": "uuid"
          }
        },
        "additionalProperties": false,
        "example": {
          "amountCents": 1299,
          "orderId": "order_1001",
          "terminalId": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
        }
      },
      "CreateTerminalRequest": {
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 128,
            "minLength": 1,
            "type": [
              "null",
              "string"
            ]
          }
        },
        "additionalProperties": false
      },
      "MerchantDailyStatsResponse": {
        "type": "object",
        "properties": {
          "date": {
            "type": [
              "null",
              "string"
            ]
          },
          "volumeCents": {
            "type": "integer",
            "format": "int64"
          },
          "transactions": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false
      },
      "MerchantProfileResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "payoutAddress": {
            "type": [
              "null",
              "string"
            ]
          },
          "webhookUrl": {
            "type": [
              "null",
              "string"
            ]
          },
          "webhookSecret": {
            "type": [
              "null",
              "string"
            ]
          },
          "rawApiKey": {
            "type": [
              "null",
              "string"
            ]
          },
          "verificationStatus": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false
      },
      "MerchantStatsResponse": {
        "type": "object",
        "properties": {
          "totalVolumeCents": {
            "type": "integer",
            "format": "int64"
          },
          "totalTransactions": {
            "type": "integer",
            "format": "int32"
          },
          "successfulTransactions": {
            "type": "integer",
            "format": "int32"
          },
          "chartData": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/MerchantDailyStatsResponse"
            }
          }
        },
        "additionalProperties": false
      },
      "MerchantWebhookPayload": {
        "type": "object",
        "properties": {
          "event": {
            "type": [
              "null",
              "string"
            ]
          },
          "data": {
            "$ref": "#/components/schemas/WebhookData"
          }
        },
        "additionalProperties": false,
        "description": "Outgoing webhook payload sent by Stendly to the merchant webhook URL."
      },
      "PaymentIntentResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "orderId": {
            "type": [
              "null",
              "string"
            ]
          },
          "expectedAmountCents": {
            "type": "integer",
            "format": "int64"
          },
          "referenceAddress": {
            "type": [
              "null",
              "string"
            ]
          },
          "destinationAddress": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "type": [
              "null",
              "string"
            ]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false,
        "example": {
          "id": "8c8b2f6b-16b3-4761-a5f0-8b8c9c5f1a11",
          "orderId": "order_1001",
          "expectedAmountCents": 1299,
          "referenceAddress": "GvHeM7QbJ...",
          "destinationAddress": "9xQeWvG816bUx9EP...",
          "status": "pending",
          "expiresAt": "2026-06-17T12:30:00Z"
        }
      },
      "TerminalResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "isActive": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "UpdateWebhookRequest": {
        "required": [
          "webhookUrl"
        ],
        "type": "object",
        "properties": {
          "webhookUrl": {
            "maxLength": 2048,
            "minLength": 1,
            "type": "string",
            "format": "uri"
          }
        },
        "additionalProperties": false,
        "example": {
          "webhookUrl": "https://merchant.example.com/stendly/webhook"
        }
      },
      "WebhookData": {
        "type": "object",
        "properties": {
          "paymentIntentId": {
            "type": "string",
            "format": "uuid"
          },
          "orderId": {
            "type": [
              "null",
              "string"
            ]
          },
          "amountCents": {
            "type": "integer",
            "format": "int64"
          },
          "expectedAmountCents": {
            "type": "integer",
            "format": "int64"
          },
          "txSignature": {
            "type": [
              "null",
              "string"
            ]
          }
        },
        "additionalProperties": false
      }
    },
    "responses": {
      "ApiError": {
        "description": "Standard API error response.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "additionalProperties": false,
              "description": "Standardized API error envelope."
            },
            "example": {
              "error": {
                "code": "BAD_REQUEST",
                "message": "Amount must be greater than 0",
                "traceId": "0HMSAMPLETRACE"
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "MerchantApiKey": {
        "type": "http",
        "description": "Merchant API key in the Authorization header. Format: Bearer st_live_...",
        "scheme": "bearer",
        "bearerFormat": "st_live_..."
      }
    },
    "callbacks": {
      "MerchantWebhook": {
        "{$request.body#/webhookUrl}": {
          "post": {
            "summary": "Receive payment intent event",
            "description": "Stendly sends this POST request to the merchant webhook URL configured with PATCH /api/b2b/merchants/webhook.",
            "parameters": [
              {
                "name": "X-Stendly-Signature",
                "in": "header",
                "description": "HMAC-SHA256 signature over timestamp + raw JSON payload. Format: t={unix_timestamp},v1={hex_digest}.",
                "required": true,
                "schema": {
                  "type": "string",
                  "example": "t=1714567890,v1=3f4c2d8a9b0e1f2a3c4d5e6f7081920a"
                }
              },
              {
                "name": "X-Stendly-Idempotency-Key",
                "in": "header",
                "description": "Unique delivery idempotency key for this webhook attempt.",
                "required": true,
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            ],
            "requestBody": {
              "content": {
                "application/json": {
                  "schema": {
                    "description": "Outgoing webhook payload sent by Stendly to the merchant webhook URL.",
                    "$ref": "#/components/schemas/MerchantWebhookPayload"
                  },
                  "example": {
                    "event": "payment_intent.succeeded",
                    "data": {
                      "paymentIntentId": "8c8b2f6b-16b3-4761-a5f0-8b8c9c5f1a11",
                      "orderId": "order_1001",
                      "amountCents": 1299,
                      "expectedAmountCents": 1299,
                      "txSignature": "5S5kY8uJp9..."
                    }
                  }
                }
              },
              "required": true
            },
            "responses": {
              "2XX": {
                "description": "Webhook accepted by merchant endpoint."
              }
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "B2B Dashboard"
    },
    {
      "name": "Merchants"
    }
  ]
}