marketplace-doc
    • Data Ingestion
    • Errors
    • Introduction
    • Loan API & Deduction Lifecycle
    • Getting Started
    • OAuth
    • Webhooks
    • Embedded Journey
    • OpenSylo Marketplace Integration API
      • OAuth 2.0
        • Start OAuth authorization
        • Exchange authorization code or refresh token
        • Revoke a token
        • Discover OAuth capabilities
      • Data Ingestion
        • Submit single merchant data
        • Submit bulk merchant data
        • Poll batch processing status
        • Get merchant credit score
        • Data ingestion health check
      • Sales & Events
        • Submit a sales event
        • Submit a repayment event
        • Submit an account flag
      • Loan API
        • Get active loans for a merchant
        • Get loan status
        • Validate deduction amounts
        • Bulk loan status
      • Inbound Webhooks
        • Repayment events
        • Settlement events
      • Outbound Webhooks
        • loan.approved
        • loan.disbursed
        • loan.repayment_updated
        • loan.nearly_complete
        • loan.completed
        • loan.defaulted
        • merchant.created
        • kyc.submitted
        • kyc.approved
        • kyc.rejected
        • funding_request.created
        • funding_request.fulfilled
        • funding_request.rejected
      • Embedded Journey (Marketplace API)
        • Create (or fetch) a merchant
        • Get merchant status (KYC, credit score, funding requests)
        • Update business KYC information
        • Add directors (bulk)
        • Attach a KYC document
        • Submit KYC for review
        • Submit sales data for credit scoring
        • Create a funding request
        • Mint an embed token for the hosted journey
      • Schemas
        • TokenRequest
        • TokenResponse
        • OAuthError
        • ClientMetadataResponse
        • MerchantIdentity
        • SalesPerformance
        • RevenueConsistency
        • FulfillmentMetrics
        • PayoutCashFlow
        • PlatformDependency
        • HistoricalCredit
        • BehavioralRisk
        • MonthlyHistoryEntry
        • MerchantDataRequest
        • CreditScore
        • LoanEligibilityResult
        • MerchantDataResponse
        • BulkMerchantDataRequest
        • AsyncBulkProcessingResponse
        • BatchStatusResponse
        • SalesEventRequest
        • RepaymentEventRequest
        • AccountFlagRequest
        • MerchantInfo
        • LenderInfo
        • RepaymentInfo
        • LoanTermsInfo
        • ActiveLoan
        • ActiveLoansSummary
        • ActiveLoansResponse
        • LoanStatusRepayment
        • LoanStatusResponse
        • ValidateDeductionsRequest
        • DeductionItem
        • DeductionSummary
        • ValidateDeductionsResponse
        • BulkLoanStatusRequest
        • BulkLoanStatusItem
        • BulkStatusSummary
        • BulkLoanStatusResponse
        • WebhookMarketplace
        • WebhookMerchant
        • WebhookLoan
        • DeductionDetails
        • SourceTransaction
        • LoanBalance
        • RepaymentDeductedWebhook
        • FailureDetails
        • RepaymentFailedWebhook
        • ReversalDetails
        • RepaymentReversedWebhook
        • SettlementDetails
        • SettlementSummaryByStatus
        • SettlementSummary
        • SettlementLoanIncluded
        • BankTransferDetails
        • SettlementCreatedWebhook
        • SettlementTransferredWebhook
        • TransferDetails
        • WebhookAckResponse
        • OutboundLoan
        • OutboundMerchant
        • OutboundLender
        • LoanTerms
        • RepaymentTerms
        • ScheduleInstallment
        • LoanApprovedPayload
        • DisbursementDetails
        • DisbursedRepayment
        • LoanDisbursedPayload
        • ChangeDetail
        • LoanRepaymentUpdatedPayload
        • RepaymentStatus
        • NearlyCompleteRecommendation
        • LoanNearlyCompletePayload
        • CompletionSummary
        • LoanCompletedPayload
        • DefaultDetails
        • CollectionInstructions
        • LoanDefaultedPayload
        • ApiError
        • RateLimitError
        • EmbedCreateMerchantRequest
        • EmbedCreateMerchantResponse
        • EmbedBusinessKyc
        • EmbedDirectorInfo
        • EmbedBulkDirectors
        • EmbedDirectorListItem
        • EmbedDocumentUpload
        • EmbedSalesDataAccepted
        • EmbedCreateFundingRequest
        • EmbedFundingRequestIntent
        • EmbedMerchantStatusResponse
        • EmbedTokenResponse
        • MarketplaceMerchantRef
        • MerchantCreatedPayload
        • KycStatusPayload
        • FundingRequestEventPayload
    • OpenSylo Marketplace API
      • OAuth 2.0
        • Start OAuth authorization
        • Exchange code or refresh token
        • Revoke a token
        • OAuth discovery / client metadata
      • Data Ingestion
        • Submit single merchant data
        • Submit bulk merchant data
        • Get merchant credit score
        • Integration health check
      • Loan API
        • Get active loans for a merchant
        • Get loan status
        • Validate deduction amounts
        • Bulk loan status check
      • Inbound Webhooks
        • Send repayment webhook
        • Send settlement webhook
      • Schemas
        • TokenRequest
        • TokenResponse
        • RevokeRequest
        • ClientMetadataResponse
        • MerchantIdentity
        • SalesPerformance
        • RevenueConsistency
        • FulfillmentMetrics
        • PayoutCashFlow
        • PlatformDependency
        • HistoricalCredit
        • BehavioralRisk
        • MerchantDataRequest
        • ScoreBreakdown
        • CreditScore
        • MerchantDataResponse
        • BulkMerchantDataRequest
        • BulkMerchantDataResponse
        • CreditScoreResponse
        • HealthResponse
        • ActiveLoansResponse
        • LoanStatusResponse
        • ValidateDeductionsRequest
        • ValidateDeductionsResponse
        • BulkLoanStatusRequest
        • BulkLoanStatusResponse
        • RepaymentWebhookRequest
        • SettlementWebhookRequest
        • WebhookAckResponse
        • OAuthError
        • ApiError

    Webhooks

    OpenSylo supports both inbound webhooks (marketplace to OpenSylo) and outbound webhooks (OpenSylo to marketplace).

    Inbound Webhooks (Marketplace to OpenSylo)#

    Your marketplace sends webhooks to OpenSylo to report repayment deductions and settlement events.

    Endpoints#

    EndpointPurpose
    POST /api/v1/webhooks/marketplace/repaymentRepayment events (deducted, failed, reversed)
    POST /api/v1/webhooks/marketplace/settlementSettlement events (created, transferred)

    Required Headers#

    HeaderRequiredDescription
    X-Marketplace-SignatureYesHMAC-SHA256 signature of the payload
    X-Marketplace-TimestampYesUnix timestamp (seconds) of when the webhook was sent
    X-Marketplace-IdYesYour marketplace ID
    X-Marketplace-Event-IdNoUnique idempotency key for the event

    Signature Generation#

    Generate the signature using HMAC-SHA256:
    payload = "<timestamp>.<JSON_body>"
    signature = "sha256=" + HMAC-SHA256(your_api_secret, payload)
    TypeScript implementation:
    Bash implementation:
    Timestamp tolerance: The timestamp must be within 5 minutes (300 seconds) of the current server time.

    Inbound Event Types#

    EventDescription
    repayment.deductedA repayment was successfully deducted from a merchant's sale/settlement
    repayment.failedA repayment deduction attempt failed
    repayment.reversedA previously deducted repayment was reversed
    settlement.createdA settlement batch was created containing repayment deductions
    settlement.transferredA settlement was transferred via bank transfer

    Example -- repayment.deducted#

    {
      "event": "repayment.deducted",
      "event_id": "evt_rep_001",
      "timestamp": "2026-01-29T10:30:00.000Z",
      "marketplace": {
        "id": "marketplace_uuid",
        "name": "Your Marketplace"
      },
      "merchant": {
        "marketplace_id": "your_internal_merchant_id",
        "opensylo_id": "opensylo_merchant_uuid"
      },
      "loan": {
        "opensylo_id": "loan_uuid",
        "opensylo_reference": "LOAN-2026-001"
      },
      "deduction": {
        "reference": "deduct_ref_001",
        "amount": 5000,
        "currency": "NGN",
        "deducted_at": "2026-01-29T10:30:00.000Z"
      },
      "source_transaction": {
        "id": "order_123",
        "type": "sale",
        "gross_amount": 25000,
        "timestamp": "2026-01-29T10:25:00.000Z"
      },
      "loan_balance": {
        "total_due": 100000,
        "total_paid": 55000,
        "outstanding": 45000
      }
    }

    Example -- repayment.failed#

    {
      "event": "repayment.failed",
      "event_id": "evt_rep_002",
      "timestamp": "2026-01-30T11:00:00.000Z",
      "marketplace": {
        "id": "marketplace_uuid",
        "name": "Your Marketplace"
      },
      "merchant": {
        "marketplace_id": "your_internal_merchant_id",
        "opensylo_id": "opensylo_merchant_uuid"
      },
      "loan": {
        "opensylo_id": "loan_uuid",
        "opensylo_reference": "LOAN-2026-001"
      },
      "failure": {
        "reference": "fail_ref_001",
        "attempted_amount": 5000,
        "currency": "NGN",
        "reason": "Merchant wallet balance insufficient for deduction",
        "code": "INSUFFICIENT_BALANCE",
        "attempted_at": "2026-01-30T11:00:00.000Z"
      },
      "source_transaction": {
        "id": "order_456",
        "type": "sale",
        "gross_amount": 3000,
        "timestamp": "2026-01-30T10:55:00.000Z"
      },
      "loan_balance": {
        "total_due": 100000,
        "total_paid": 55000,
        "outstanding": 45000
      }
    }

    Example -- repayment.reversed#

    {
      "event": "repayment.reversed",
      "event_id": "evt_rep_003",
      "timestamp": "2026-02-01T14:00:00.000Z",
      "marketplace": {
        "id": "marketplace_uuid",
        "name": "Your Marketplace"
      },
      "merchant": {
        "marketplace_id": "your_internal_merchant_id",
        "opensylo_id": "opensylo_merchant_uuid"
      },
      "loan": {
        "opensylo_id": "loan_uuid",
        "opensylo_reference": "LOAN-2026-001"
      },
      "reversal": {
        "reference": "rev_ref_001",
        "original_deduction_reference": "deduct_ref_001",
        "amount": 5000,
        "currency": "NGN",
        "reason": "Original sale was refunded by buyer",
        "reversed_at": "2026-02-01T14:00:00.000Z"
      },
      "loan_balance": {
        "total_due": 100000,
        "total_paid": 50000,
        "outstanding": 50000
      }
    }

    Example -- settlement.created#

    {
      "event": "settlement.created",
      "event_id": "evt_stl_001",
      "timestamp": "2026-02-03T00:00:00.000Z",
      "marketplace": {
        "id": "marketplace_uuid",
        "name": "Your Marketplace"
      },
      "settlement": {
        "reference": "stl_2026_w05",
        "period_start": "2026-01-27T00:00:00.000Z",
        "period_end": "2026-02-02T23:59:59.000Z",
        "currency": "NGN",
        "created_at": "2026-02-03T00:00:00.000Z"
      },
      "summary": {
        "total_deductions": 12,
        "total_amount": 60000,
        "merchants_included": 3
      },
      "loans_included": [
        {
          "opensylo_id": "loan_uuid_1",
          "opensylo_reference": "LOAN-2026-001",
          "deduction_count": 8,
          "deduction_total": 40000
        },
        {
          "opensylo_id": "loan_uuid_2",
          "opensylo_reference": "LOAN-2026-002",
          "deduction_count": 4,
          "deduction_total": 20000
        }
      ],
      "bank_transfer": {
        "status": "pending",
        "destination_bank": "OpenSylo Collections",
        "destination_account": "0123456789"
      }
    }

    Example -- settlement.transferred#

    {
      "event": "settlement.transferred",
      "event_id": "evt_stl_002",
      "timestamp": "2026-02-03T10:30:00.000Z",
      "marketplace": {
        "id": "marketplace_uuid",
        "name": "Your Marketplace"
      },
      "settlement": {
        "reference": "stl_2026_w05",
        "currency": "NGN"
      },
      "transfer": {
        "reference": "txn_bank_001",
        "amount": 60000,
        "bank_name": "OpenSylo Collections",
        "account_number": "0123456789",
        "transferred_at": "2026-02-03T10:30:00.000Z",
        "bank_reference": "NIP/230203/ABCDEF"
      }
    }

    Webhook Response#

    OpenSylo responds with an acknowledgment:
    {
      "status": "received",
      "event_id": "evt_rep_001",
      "opensylo_reference": "txn_uuid",
      "received_at": "2026-01-29T10:30:01.000Z"
    }

    Rate Limiting#

    Inbound webhooks are rate-limited to 100 requests per 60 seconds per marketplace.
    If the limit is exceeded, OpenSylo responds with HTTP 429 Too Many Requests and a Retry-After header indicating how many seconds to wait before retrying.
    Recommendation: Implement client-side rate limiting to stay within the allowed threshold and avoid rejected requests.

    Outbound Webhooks (OpenSylo to Marketplace)#

    OpenSylo sends webhooks to your configured webhook URL to notify you of loan lifecycle events.

    Outbound Webhook Headers#

    Every outbound webhook from OpenSylo includes the following headers:
    HeaderDescription
    X-OpenSylo-Signaturesha256= + HMAC-SHA256 hex digest
    X-OpenSylo-TimestampUnix timestamp in seconds
    X-OpenSylo-Event-IdUnique event ID (e.g., evt_loan_approved_1706529000_a1b2c3d4)

    Signature Verification#

    When receiving a webhook from OpenSylo, verify the signature using the webhook secret provided during marketplace setup.
    TypeScript implementation:
    Always use a constant-time comparison (timingSafeEqual) to prevent timing attacks. Reject any request where the timestamp is more than 5 minutes old.

    Outbound Event Types#

    EventDescription
    loan.approvedA loan has been approved for one of your merchants. Includes loan terms, repayment terms, and optional repayment schedule.
    loan.disbursedLoan funds have been disbursed to the merchant. Includes disbursement details and repayment start date. Start deducting repayments.
    loan.repayment_updatedRepayment terms have changed (deduction percentage, due date). Update your deduction logic.
    loan.nearly_completeLoan is close to full repayment (>90% paid). Includes max_deduction_amount -- cap the next deduction to avoid overpayment.
    loan.completedLoan is fully repaid. Stop all deductions immediately.
    loan.defaultedLoan has defaulted. Includes collection_instructions with priority level.
    The following events are sent only for merchants you onboarded through the embedded application journey (Marketplace API). They use the same signature scheme and retry policy as all other outbound webhooks.
    EventDescription
    merchant.createdA merchant was created via POST /api/v1/marketplace-api/merchants.
    kyc.submittedThe merchant submitted KYC for review (via API or the embedded journey).
    kyc.approvedKYC was approved. Pending funding requests become eligible for fulfillment.
    kyc.rejectedKYC was rejected. Includes rejection_reason -- the merchant can correct and resubmit.
    funding_request.createdA funding request was created (via API or the embedded journey).
    funding_request.fulfilledThe funding request was promoted to a real loan. Includes loan_id -- the standard loan.* events follow.
    funding_request.rejectedFulfillment was blocked by credit policy. Includes failure_reason.

    Example -- loan.approved#

    {
      "event": "loan.approved",
      "event_id": "evt_loan_001",
      "timestamp": "2026-01-29T14:00:00.000Z",
      "loan": {
        "id": "loan_uuid",
        "reference": "LOAN-2026-001",
        "status": "APPROVED"
      },
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "your_internal_merchant_id"
      },
      "lender": {
        "id": "lender_uuid",
        "name": "FinCo Lending"
      },
      "terms": {
        "principal_amount": 500000,
        "interest_rate": 5.0,
        "tenor_days": 90,
        "total_repayment": 525000,
        "currency": "NGN"
      },
      "repayment": {
        "method": "sales_deduction",
        "deduction_percentage": 10,
        "minimum_deduction": 500,
        "start_date": "2026-02-01T00:00:00.000Z",
        "due_date": "2026-05-01T00:00:00.000Z"
      },
      "schedule": [
        { "installment": 1, "due_date": "2026-02-01", "amount": 175000 },
        { "installment": 2, "due_date": "2026-03-01", "amount": 175000 },
        { "installment": 3, "due_date": "2026-04-01", "amount": 175000 }
      ]
    }

    Example -- loan.disbursed#

    {
      "event": "loan.disbursed",
      "event_id": "evt_loan_002",
      "timestamp": "2026-02-01T09:00:00.000Z",
      "loan": {
        "id": "loan_uuid",
        "reference": "LOAN-2026-001",
        "status": "DISBURSED"
      },
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "your_internal_merchant_id"
      },
      "disbursement": {
        "amount": 500000,
        "currency": "NGN",
        "method": "bank_transfer",
        "bank_name": "Access Bank",
        "account_number": "****6789",
        "disbursed_at": "2026-02-01T09:00:00.000Z",
        "reference": "DSB-2026-001"
      },
      "repayment_start": {
        "effective_date": "2026-02-01T00:00:00.000Z",
        "deduction_percentage": 10,
        "minimum_deduction": 500
      },
      "action_required": "start_deductions",
      "message": "Loan disbursed. Begin deducting 10% from merchant sales immediately."
    }

    Example -- loan.repayment_updated#

    {
      "event": "loan.repayment_updated",
      "event_id": "evt_loan_003",
      "timestamp": "2026-03-01T12:00:00.000Z",
      "loan": {
        "id": "loan_uuid",
        "reference": "LOAN-2026-001",
        "status": "ACTIVE"
      },
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "your_internal_merchant_id"
      },
      "changes": {
        "deduction_percentage": {
          "previous": 10,
          "new": 15
        },
        "due_date": {
          "previous": "2026-05-01T00:00:00.000Z",
          "new": "2026-04-15T00:00:00.000Z"
        }
      },
      "reason": "Repayment schedule adjusted due to missed milestones",
      "updated_schedule": [
        { "installment": 2, "due_date": "2026-03-01", "amount": 200000 },
        { "installment": 3, "due_date": "2026-04-01", "amount": 200000 }
      ],
      "action_required": "update_deduction_settings",
      "message": "Deduction percentage changed from 10% to 15%. Update your deduction logic."
    }

    Example -- loan.nearly_complete#

    {
      "event": "loan.nearly_complete",
      "event_id": "evt_loan_004",
      "timestamp": "2026-04-10T08:00:00.000Z",
      "loan": {
        "id": "loan_uuid",
        "reference": "LOAN-2026-001",
        "status": "ACTIVE"
      },
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "your_internal_merchant_id"
      },
      "repayment_status": {
        "total_due": 525000,
        "total_paid": 510000,
        "outstanding": 15000,
        "percent_complete": 97.14
      },
      "recommendation": {
        "max_deduction_amount": 15000,
        "message": "Cap the next deduction at NGN 15,000 to avoid over-collection."
      },
      "action_required": "cap_deductions",
      "message": "Loan is 97.14% repaid. Cap next deduction to NGN 15,000."
    }

    Example -- loan.completed#

    {
      "event": "loan.completed",
      "event_id": "evt_loan_005",
      "timestamp": "2026-04-15T09:00:00.000Z",
      "loan": {
        "id": "loan_uuid",
        "reference": "LOAN-2026-001",
        "status": "REPAID"
      },
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "your_internal_merchant_id"
      },
      "summary": {
        "principal_repaid": 500000,
        "interest_repaid": 25000,
        "total_repaid": 525000,
        "total_deductions": 42,
        "first_deduction_at": "2026-02-01T10:00:00.000Z",
        "final_deduction_at": "2026-04-15T08:55:00.000Z",
        "completed_at": "2026-04-15T09:00:00.000Z"
      },
      "action_required": "stop_deductions",
      "message": "Loan fully repaid. Stop all deductions for this loan immediately."
    }

    Example -- loan.defaulted#

    {
      "event": "loan.defaulted",
      "event_id": "evt_loan_006",
      "timestamp": "2026-06-01T00:00:00.000Z",
      "loan": {
        "id": "loan_uuid",
        "reference": "LOAN-2026-001",
        "status": "DEFAULTED"
      },
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "your_internal_merchant_id"
      },
      "default_details": {
        "total_due": 525000,
        "total_paid": 350000,
        "outstanding": 175000,
        "days_overdue": 31,
        "last_payment_at": "2026-04-30T15:00:00.000Z",
        "defaulted_at": "2026-06-01T00:00:00.000Z"
      },
      "collection_instructions": {
        "priority": "HIGH",
        "deduction_percentage": 25,
        "withhold_settlements": true,
        "message": "Increase deduction rate to 25%. Withhold merchant settlements until further notice."
      },
      "action_required": "escalate_collection",
      "message": "Loan has defaulted. Follow collection instructions immediately."
    }

    Example -- merchant.created#

    {
      "event": "merchant.created",
      "event_id": "evt_merchant.created_a1b2c3d4",
      "timestamp": "2026-06-10T10:00:00.123Z",
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "marketplace_uuid",
        "third_party_customer_id": "mkt_merchant_8421"
      },
      "business_name": "Mama Cass Foods Ltd"
    }
    third_party_customer_id is the ID you supplied when creating the merchant -- use it to correlate the event with your own records.

    Example -- kyc.submitted#

    {
      "event": "kyc.submitted",
      "event_id": "evt_kyc.submitted_b2c3d4e5",
      "timestamp": "2026-06-10T10:05:00.123Z",
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "marketplace_uuid",
        "third_party_customer_id": "mkt_merchant_8421"
      },
      "kyc_status": "SUBMITTED",
      "rejection_reason": null
    }

    Example -- kyc.approved#

    {
      "event": "kyc.approved",
      "event_id": "evt_kyc.approved_c3d4e5f6",
      "timestamp": "2026-06-11T09:00:00.123Z",
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "marketplace_uuid",
        "third_party_customer_id": "mkt_merchant_8421"
      },
      "kyc_status": "APPROVED",
      "rejection_reason": null
    }
    Once KYC is approved, any pending funding request is fulfilled automatically (typically within 2 minutes) if a credit score exists -- expect a funding_request.fulfilled or funding_request.rejected event to follow.

    Example -- kyc.rejected#

    {
      "event": "kyc.rejected",
      "event_id": "evt_kyc.rejected_d4e5f6g7",
      "timestamp": "2026-06-11T09:00:00.123Z",
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "marketplace_uuid",
        "third_party_customer_id": "mkt_merchant_8421"
      },
      "kyc_status": "REJECTED",
      "rejection_reason": "CAC certificate expired. Please upload a valid document."
    }
    Surface rejection_reason to the merchant -- they can correct the issue in the embedded journey and resubmit.

    Example -- funding_request.created#

    {
      "event": "funding_request.created",
      "event_id": "evt_funding_request.created_e5f6g7h8",
      "timestamp": "2026-06-10T10:10:00.123Z",
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "marketplace_uuid",
        "third_party_customer_id": "mkt_merchant_8421"
      },
      "funding_request": {
        "id": "fr_uuid",
        "amount_requested": 2000000,
        "tenor_days": 90,
        "purpose": "Inventory purchase",
        "status": "PENDING",
        "loan_id": null,
        "failure_reason": null
      }
    }

    Example -- funding_request.fulfilled#

    {
      "event": "funding_request.fulfilled",
      "event_id": "evt_funding_request.fulfilled_f6g7h8i9",
      "timestamp": "2026-06-11T09:02:00.123Z",
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "marketplace_uuid",
        "third_party_customer_id": "mkt_merchant_8421"
      },
      "funding_request": {
        "id": "fr_uuid",
        "amount_requested": 2000000,
        "tenor_days": 90,
        "purpose": "Inventory purchase",
        "status": "FULFILLED",
        "loan_id": "loan_uuid",
        "failure_reason": null
      }
    }
    A real loan now exists (loan_id) and proceeds through the standard lifecycle -- the loan.* events above apply from here on.

    Example -- funding_request.rejected#

    {
      "event": "funding_request.rejected",
      "event_id": "evt_funding_request.rejected_g7h8i9j0",
      "timestamp": "2026-06-11T09:02:00.123Z",
      "merchant": {
        "opensylo_id": "merchant_uuid",
        "marketplace_id": "marketplace_uuid",
        "third_party_customer_id": "mkt_merchant_8421"
      },
      "funding_request": {
        "id": "fr_uuid",
        "amount_requested": 2000000,
        "tenor_days": 90,
        "purpose": "Inventory purchase",
        "status": "REJECTED",
        "loan_id": null,
        "failure_reason": "Requested amount NGN 2,000,000 exceeds lending cap of NGN 1,500,000"
      }
    }
    The merchant can submit a new request (e.g. a smaller amount) -- each request is a fresh intent.

    Retry Policy#

    OpenSylo retries failed webhook deliveries with exponential backoff:
    AttemptDelay
    1Immediate
    21 minute
    35 minutes
    430 minutes
    52 hours
    624 hours
    After 6 failed attempts, the webhook is marked as failed. Your webhook endpoint should return a 2xx status code to acknowledge receipt.

    Webhook Headers Reference#

    HeaderDirectionDescription
    X-Marketplace-SignatureInbound (you to OpenSylo)sha256= + HMAC-SHA256 hex digest
    X-Marketplace-TimestampInbound (you to OpenSylo)Unix timestamp in seconds
    X-Marketplace-IdInbound (you to OpenSylo)Your marketplace UUID
    X-Marketplace-Event-IdInbound (you to OpenSylo)Idempotency key (optional)
    X-OpenSylo-SignatureOutbound (OpenSylo to you)sha256= + HMAC-SHA256 hex digest
    X-OpenSylo-TimestampOutbound (OpenSylo to you)Unix timestamp in seconds
    X-OpenSylo-Event-IdOutbound (OpenSylo to you)Unique event ID

    Signature Formula#

    payload = "<unix_timestamp>.<JSON.stringify(body)>"
    signature = "sha256=" + HMAC_SHA256(api_secret, payload).hexdigest()
    Modified at 2026-06-10 14:59:30
    Previous
    OAuth
    Next
    Embedded Journey
    Built with