{
  "openapi": "3.0.3",
  "info": {
    "title": "Strawberry ID — merchant & provisioning API",
    "version": "1.0.0",
    "description": "Concise reference for server-to-server integration. User-facing auth and onboarding routes are omitted here; see /developers/api-overview.md on the developer portal."
  },
  "servers": [{ "url": "https://www.strawberryid.com/api", "description": "Production (default)" }],
  "tags": [
    { "name": "Merchant v1", "description": "Bearer sk_test_* or sk_live_*" },
    { "name": "Provisioning", "description": "Merchant creation, keys, webhooks (no merchant API key)" }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_test_… or sk_live_…"
      }
    },
    "schemas": {
      "ConsumerStrawberryId": {
        "type": "string",
        "description": "End user's personal Strawberry ID (SR1-…), NOT the merchant business code (SRM-…). Canonical: SR1- plus 4 Crockford chars, hyphen, 4 chars, hyphen, 1 check char (e.g. SR1-B835-V4ZW-M). Compact: SR1 immediately followed by 9 Crockford base32 chars without hyphens (e.g. SR1B835V4ZWM). Alphabet: A–Z except I,L,O,U and digits 2–9. Server normalizes case and spacing.",
        "examples": ["SR1-B835-V4ZW-M", "SR1B835V4ZWM"]
      },
      "DataRequestBody": {
        "type": "object",
        "required": ["strawberry_id", "requested_fields"],
        "properties": {
          "strawberry_id": { "$ref": "#/components/schemas/ConsumerStrawberryId" },
          "requested_fields": {
            "type": "array",
            "items": { "type": "string" },
            "example": ["strawberry_id", "display_name", "kyc_status"]
          }
        }
      },
      "KycVerificationBody": {
        "type": "object",
        "required": ["kind", "id", "verification_consent"],
        "properties": {
          "user_id": { "type": "string", "description": "Internal user id (alternative to strawberry_id)" },
          "strawberry_id": { "$ref": "#/components/schemas/ConsumerStrawberryId" },
          "kind": { "type": "string", "enum": ["bvn", "nin", "vnin", "phone", "nin_phone"] },
          "id": { "type": "string", "minLength": 5, "maxLength": 64 },
          "verification_consent": { "type": "boolean", "enum": [true] },
          "tier": { "type": "string", "maxLength": 32 },
          "validation": {
            "type": "object",
            "properties": {
              "first_name": { "type": "string", "maxLength": 120 },
              "last_name": { "type": "string", "maxLength": 120 },
              "date_of_birth": { "type": "string", "maxLength": 32 },
              "selfie": { "type": "string", "maxLength": 12000000 }
            }
          }
        }
      },
      "CreateMerchantBody": {
        "type": "object",
        "required": ["name", "legalName", "contactName", "contactEmail", "country", "businessType"],
        "properties": {
          "name": { "type": "string" },
          "legalName": { "type": "string" },
          "contactName": { "type": "string" },
          "contactEmail": { "type": "string", "format": "email" },
          "supportEmail": { "type": "string", "format": "email" },
          "websiteUrl": { "type": "string", "format": "uri" },
          "country": { "type": "string" },
          "businessType": { "type": "string" },
          "registrationNumber": { "type": "string" }
        }
      },
      "ApiKeyBody": {
        "type": "object",
        "required": ["environment"],
        "properties": {
          "environment": { "type": "string", "enum": ["TEST", "LIVE"] }
        }
      },
      "WebhookRegisterBody": {
        "type": "object",
        "required": ["url"],
        "properties": {
          "url": { "type": "string", "format": "uri" }
        }
      },
      "MerchantWalletRefundBody": {
        "type": "object",
        "description": "Reverse a settled One Wallet payment to the customer’s primary wallet. Provide `transaction_id` (platform id) or `reference` (checkout reference). Omit `amount` for a full refund.",
        "properties": {
          "transaction_id": { "type": "string", "description": "Strawberry `Transaction.id` for the original PAYMENT" },
          "reference": { "type": "string", "description": "Original transaction `reference` from checkout" },
          "amount": { "type": "number", "exclusiveMinimum": 0, "description": "Partial refund amount; omit for full original amount" },
          "currency": { "type": "string", "default": "NGN" },
          "reason": { "type": "string", "maxLength": 500 },
          "merchant_reference": { "type": "string", "maxLength": 120, "description": "Your idempotency-friendly label; echoed as `merchantReference` on webhooks" },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["amount"],
              "properties": {
                "amount": { "type": "number", "exclusiveMinimum": 0 },
                "currency": { "type": "string", "default": "NGN" },
                "reason": { "type": "string", "maxLength": 240 }
              }
            }
          }
        }
      }
    }
  },
  "paths": {
    "/v1/whoami": {
      "get": {
        "tags": ["Merchant v1"],
        "security": [{ "bearerAuth": [] }],
        "summary": "Merchant status and API access flags",
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/v1/data-requests": {
      "post": {
        "tags": ["Merchant v1"],
        "security": [{ "bearerAuth": [] }],
        "summary": "Request user consent for identity fields",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/DataRequestBody" } }
          }
        },
        "responses": { "201": { "description": "Created" }, "400": { "description": "Validation error" } }
      }
    },
    "/v1/identity": {
      "get": {
        "tags": ["Merchant v1"],
        "security": [{ "bearerAuth": [] }],
        "summary": "Read approved user fields",
        "parameters": [
          {
            "name": "strawberry_id",
            "in": "query",
            "required": true,
            "schema": { "$ref": "#/components/schemas/ConsumerStrawberryId" }
          },
          { "name": "fields", "in": "query", "schema": { "type": "string", "description": "Comma-separated" } }
        ],
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/v1/kyc/verifications": {
      "post": {
        "tags": ["Merchant v1"],
        "security": [{ "bearerAuth": [] }],
        "summary": "Run Strawberry-managed KYC for a linked user",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/KycVerificationBody" } }
          }
        },
        "responses": { "201": { "description": "Created" } }
      }
    },
    "/v1/kyc/verifications/{reference}": {
      "get": {
        "tags": ["Merchant v1"],
        "security": [{ "bearerAuth": [] }],
        "summary": "Fetch verification by provider reference",
        "parameters": [{ "name": "reference", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "OK" }, "404": { "description": "Not found" } }
      }
    },
    "/v1/refunds": {
      "post": {
        "tags": ["Merchant v1"],
        "security": [{ "bearerAuth": [] }],
        "summary": "Refund a One Wallet payment to the customer wallet",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/MerchantWalletRefundBody" } }
          }
        },
        "responses": {
          "201": { "description": "Refund completed; customer wallet credited" },
          "400": { "description": "Validation or business rule error (see error code)" },
          "403": { "description": "Forbidden" },
          "404": { "description": "Transaction not found for this merchant" },
          "409": { "description": "Conflict (already refunded or idempotency)" },
          "429": { "description": "Rate limited" }
        }
      }
    },
    "/merchants": {
      "post": {
        "tags": ["Provisioning"],
        "summary": "Create merchant (sandbox-ready review)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/CreateMerchantBody" } }
          }
        },
        "responses": { "201": { "description": "Created" } }
      }
    },
    "/merchants/{id}/api-keys": {
      "post": {
        "tags": ["Provisioning"],
        "summary": "Create API key",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/ApiKeyBody" } }
          }
        },
        "responses": { "201": { "description": "Created" } }
      }
    },
    "/merchants/{id}/webhooks": {
      "post": {
        "tags": ["Provisioning"],
        "summary": "Register webhook URL",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/WebhookRegisterBody" } }
          }
        },
        "responses": { "201": { "description": "Created" } }
      }
    }
  }
}
