Skip to main content
PUT
/
v2
/
onboard
/
{refNo}
Update Onboarding Data
curl --request PUT \
  --url https://kyc.sbx.moduluslabs.io/v2/onboard/{refNo} \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "merchantName": "<string>",
  "modeOfPayments": [
    "CREDIT_CARD"
  ],
  "currency": "PHP",
  "tin": "<string>",
  "industry": "<string>",
  "serviceDescription": "<string>",
  "isBrickAndMortarStore": true,
  "address": {
    "office": {
      "city": "<string>",
      "line1": "<string>",
      "state": "<string>",
      "postalCode": "<string>",
      "contactNumber": "<string>",
      "barangay": "<string>",
      "buildingNameAndNumber": "<string>"
    },
    "registered": {
      "city": "<string>",
      "line1": "<string>",
      "state": "<string>",
      "postalCode": "<string>",
      "contactNumber": "<string>",
      "barangay": "<string>",
      "buildingNameAndNumber": "<string>"
    }
  },
  "representatives": {
    "authorized": {
      "firstName": "<string>",
      "lastName": "<string>",
      "emailAddress": "[email protected]",
      "contactNumber": "<string>",
      "dateOfBirth": "2023-12-25",
      "position": "<string>",
      "middleName": "<string>",
      "tin": "<string>",
      "sss": "<string>",
      "mothersMaidenName": "<string>",
      "gender": "MALE"
    },
    "escalation": {
      "firstName": "<string>",
      "lastName": "<string>",
      "emailAddress": "[email protected]",
      "contactNumber": "<string>",
      "dateOfBirth": "2023-12-25",
      "tin": "<string>",
      "sss": "<string>",
      "position": "<string>"
    }
  },
  "banks": [
    {
      "accountDepositType": "BANK",
      "currency": "PHP",
      "accountType": "SAVINGS",
      "bankName": "<string>",
      "accountName": "<string>",
      "accountNumber": "<string>",
      "preferredSettlementRail": "instapay",
      "bankCode": "<string>"
    }
  ],
  "legalName": "<string>",
  "businessHandle": "<string>",
  "incorporators": [
    {
      "firstName": "<string>",
      "lastName": "<string>",
      "emailAddress": "[email protected]",
      "contactNumber": "<string>",
      "dateOfBirth": "2023-12-25",
      "address": {
        "city": "<string>",
        "line1": "<string>",
        "state": "<string>",
        "postalCode": "<string>",
        "contactNumber": "<string>",
        "barangay": "<string>",
        "buildingNameAndNumber": "<string>"
      },
      "middleName": "<string>"
    }
  ],
  "signatories": [
    {
      "firstName": "<string>",
      "lastName": "<string>",
      "position": "<string>",
      "middleName": "<string>"
    }
  ],
  "websites": {
    "businessWebsiteUrl": "<string>",
    "isBusinessWebsiteUnderDevelopment": true,
    "facebookUrl": "<string>",
    "twitterUrl": "<string>",
    "instagramUrl": "<string>",
    "tiktokUrl": "<string>"
  }
}
'
{
  "onboardingStatus": "PENDING",
  "onboardingReferenceNumber": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}

Overview

Updates the onboarding data for a merchant using the onboarding reference number. This endpoint allows merchants to correct and resubmit their information after their application has been declined.
Status Requirement: Regular users can only update merchants in DECLINED status. Upon successful update, the merchant’s status changes to PENDING for re-review.
Super Admin Exception: Super Admins can update merchants in APPROVED status without changing the status.

Authentication

This endpoint requires JWT Bearer Token authentication.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Authorization Rules

User RoleRequired Merchant StatusResult Status After Update
Regular UserDECLINEDPENDING
Super AdminAPPROVEDAPPROVED (no status change)
Settlement/Checker RolesN/ANot Allowed

Path Parameters

refNo
string
required
The onboarding reference number (UUID v4 format)Format: Valid UUID v4Example: "550e8400-e29b-41d4-a716-446655440000"
Must match the authenticated user’s business record. This is the referenceNumber returned from the Onboard Merchant endpoint.

Request Body

All fields from the original onboarding request are required, except those marked as optional.

Core Business Information

Legal registered name of the businessLength: 1-500 charactersRequired for: Non-STARTER business typesExample: "Acme Corporation Inc."
merchantName
string
required
Trading name or DBA (Doing Business As) nameLength: 1-500 charactersExample: "Acme Store"
businessHandle
string
Unique business handle/slug for payment linksPattern: Alphanumeric characters, dashes, and underscores onlyRequired for: Non-STARTER business typesExample: "acme-store"
Must be unique across the system. If already taken, the request will fail.
modeOfPayments
array
required
List of accepted payment modesMin Items: 1Values: CREDIT_CARD, DEBIT_CARD, GCASH, GRABPAY, PAYMAYA, BANK_TRANSFERExample: ["CREDIT_CARD", "DEBIT_CARD", "GCASH"]
currency
string
required
Primary currency for transactionsValues: PHP, USDExample: "PHP"
tin
string
required
Tax Identification NumberLength: 1-20 charactersPattern: Numbers onlyExample: "123456789012"
industry
string
required
Business industry categoryLength: 1-200 charactersExample: "Retail"
serviceDescription
string
required
Description of services or products offeredExample: "Online retail store selling electronics and gadgets"
isBrickAndMortarStore
boolean
required
Whether the business has a physical store locationExample: true

Optional Business Fields

aubPartnerId
string
AUB (Asia United Bank) partner identifierExample: "AUB123456"
estimatedMonthlyGrossTransaction
string
Estimated monthly gross transaction volumeExample: "100000-500000"
isWantPackworksWallet
boolean
Whether the merchant wants a Packworks walletDefault: false
isWantPayMayaWallet
boolean
Whether the merchant wants a PayMaya walletDefault: false
isWantPayMayaBankAccount
boolean
Whether the merchant wants a PayMaya bank accountDefault: false

Incorporators

incorporators
array
List of business incorporatorsMin Items: 1, Max Items: 5Applicable for: Non-STARTER business types only

Signatories

signatories
array
List of authorized signatoriesMin Items: 1, Max Items: 5

Address

address
object
required
Business address information

Websites

websites
object
Business online presence

Representatives

representatives
object
required
Authorized representatives

Bank Accounts

banks
array
required
List of bank accounts for settlementMin Items: 1, Max Items: 2

Code Examples

BEARER_TOKEN="your_jwt_token_here"
REF_NO="550e8400-e29b-41d4-a716-446655440000"

curl -X PUT "https://kyc.sbx.moduluslabs.io/v2/onboard/${REF_NO}" \
  -H "Authorization: Bearer ${BEARER_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantName": "Acme Store",
    "businessHandle": "acme-store",
    "modeOfPayments": ["CREDIT_CARD", "DEBIT_CARD", "GCASH"],
    "currency": "PHP",
    "tin": "123456789012",
    "industry": "Retail",
    "serviceDescription": "Online retail store selling electronics and gadgets",
    "isBrickAndMortarStore": true,
    "address": {
      "office": {
        "city": "Manila",
        "line1": "123 Main Street",
        "buildingNameAndNumber": "Building A",
        "state": "Metro Manila",
        "postalCode": "1000",
        "contactNumber": "639171234567",
        "barangay": "Barangay 1"
      }
    },
    "representatives": {
      "authorized": {
        "firstName": "Juan",
        "lastName": "Dela Cruz",
        "emailAddress": "[email protected]",
        "contactNumber": "639171234567",
        "dateOfBirth": "1985-05-15",
        "position": "CEO"
      }
    },
    "banks": [
      {
        "accountDepositType": "BANK",
        "accountType": "SAVINGS",
        "bankName": "BDO",
        "accountName": "Acme Corporation",
        "accountNumber": "1234567890",
        "currency": "PHP",
        "preferredSettlementRail": "instapay"
      }
    ]
  }'

Response

Success Response

Status Code: 200 OK
onboardingStatus
string
required
The new status after updateValue: PENDING (for regular users)Regular users: Status changes from DECLINED → PENDING Super Admins: Status remains APPROVED
onboardingReferenceNumber
string
required
The onboarding reference number (unchanged)Format: UUID v4Example: "550e8400-e29b-41d4-a716-446655440000"
{
  "onboardingStatus": "PENDING",
  "onboardingReferenceNumber": "550e8400-e29b-41d4-a716-446655440000"
}

Error Responses

Status Code: 400
{
  "statusCode": 400,
  "message": "Unable to update. Merchant is not in declined status.",
  "error": "Bad Request"
}
Cause: Regular user attempting to update a merchant that is not in DECLINED statusSolution: Only merchants in DECLINED status can be updated by regular users
Status Code: 400
{
  "statusCode": 400,
  "message": "Unable to update. Merchant is not in approved status.",
  "error": "Bad Request"
}
Cause: Super Admin attempting to update a merchant that is not in APPROVED statusSolution: Super Admins can only update merchants in APPROVED status
Status Code: 400
{
  "statusCode": 400,
  "message": "merchantName is required.",
  "error": "Bad Request"
}
Cause: Request body validation failedSolution: Ensure all required fields are provided and meet validation rules
Status Code: 400
{
  "statusCode": 400,
  "message": "Business handle is not available",
  "error": "Bad Request"
}
Cause: The requested business handle is already taken by another merchantSolution: Choose a different business handle
Status Code: 400
{
  "statusCode": 400,
  "message": "Invalid onboarding reference number format",
  "error": "Bad Request",
  "details": {
    "refNumReceived": "invalid-uuid"
  }
}
Cause: The reference number is not a valid UUID v4 formatSolution: Ensure the reference number is a valid UUID v4
Status Code: 400
{
  "statusCode": 400,
  "message": "Onboarding record does not exist",
  "error": "Bad Request"
}
Cause: No onboarding record found for the authenticated userSolution: Verify the reference number and that the onboarding record exists
Status Code: 400
{
  "statusCode": 400,
  "message": "Onboarding reference number mismatch",
  "error": "Bad Request",
  "details": {
    "refNumReceived": "550e8400-e29b-41d4-a716-446655440000"
  }
}
Cause: The reference number doesn’t match the authenticated user’s recordSolution: Use the correct JWT token for the account that owns this record
Status Code: 400
{
  "statusCode": 400,
  "message": "Failed to update onboarding record",
  "error": "Bad Request"
}
Cause: Database transaction failed during updateSolution: Retry the request. If issue persists, contact support
Status Code: 401
{
  "statusCode": 401,
  "message": "Account not found",
  "error": "Unauthorized"
}
Cause: Invalid or missing JWT Bearer tokenSolution: Ensure valid authentication token is provided

Transaction Behavior

Atomic Transaction: All updates are performed within a database transaction. If any part fails, the entire update is rolled back and no changes are made.
The update process includes:
  1. Validating all request parameters
  2. Checking user authorization and merchant status
  3. Updating business information
  4. Updating incorporators and signatories
  5. Updating addresses and representatives
  6. Updating bank accounts
  7. Changing status to PENDING (for regular users)
If any step fails, no changes are persisted.

Validation Rules Summary

Business Type

Non-STARTER businesses require legalName and businessHandle

Bank Accounts

When not NO_ACCOUNT: bankName, accountName, accountNumber, currency required

Bank Type

When accountDepositType is BANK: accountType is also required

Website

If businessWebsiteUrl provided: isBusinessWebsiteUnderDevelopment required

Status Change Flow

1

Merchant is DECLINED

Admin has declined the merchant’s onboarding application with a reason
2

Merchant Updates Data

Merchant corrects the issues and submits update via this endpoint
3

Status Changes to PENDING

Upon successful update, status automatically changes to PENDING
4

Admin Re-reviews

Admin reviews the updated information and either approves or declines again

Best Practices

Before updating, fetch the current onboarding data to pre-fill your form:
// 1. Get current data
const currentData = await retrieveOnboardingData(refNo);

// 2. Let user edit the data
const updatedData = await showEditForm(currentData);

// 3. Submit the update
const result = await updateOnboardingData(refNo, updatedData);
Review the decline reason to know what to fix:
const status = await getOnboardingStatus(refNo);

if (status.onboardingStatus === 'DECLINED') {
  console.log('Reason:', status.declinedReason);
  // Show decline reason to user
  // Highlight fields that need correction
}
Validate all required fields client-side to catch errors early:
function validateOnboardingData(data) {
  const errors = [];

  if (!data.merchantName) {
    errors.push('Merchant name is required');
  }

  if (!data.tin || !/^\d+$/.test(data.tin)) {
    errors.push('TIN must contain only numbers');
  }

  if (data.banks.length === 0) {
    errors.push('At least one bank account is required');
  }

  return errors;
}
Check if business handle is available before submitting:
async function updateWithRetry(refNo, data) {
  try {
    return await updateOnboardingData(refNo, data);
  } catch (error) {
    if (error.message.includes('Business handle is not available')) {
      // Suggest alternative handles
      data.businessHandle = `${data.businessHandle}-${Date.now()}`;
      return await updateOnboardingData(refNo, data);
    }
    throw error;
  }
}
Include optional fields from original submission to avoid losing data:
// Don't just update changed fields
const updateData = {
  ...currentData, // Start with all current data
  ...changedFields, // Override with changes
  // This preserves optional fields like websites, signatories, etc.
};

Use Cases

Fix Declined Application

Correct issues identified in decline reason and resubmit

Update Business Info

Update business details after changes (Super Admin only for approved)

Add Missing Documents

Add information that was missing in original submission

Correct Validation Errors

Fix validation issues from initial onboarding

Troubleshooting

Error: Unable to update. Merchant is not in declined status.Issue: Regular users cannot update approved merchantsSolution:
  • Only DECLINED merchants can be updated by regular users
  • If you need to update an APPROVED merchant, contact a Super Admin
  • To update business details after approval, create a new onboarding request
Issue: Update fails with Failed to update onboarding recordPossible Causes:
  • Database connectivity issues
  • Data integrity constraints violated
  • Concurrent updates from multiple sources
Solution:
  • Retry the request after a short delay
  • Ensure no concurrent updates are happening
  • Contact support if issue persists
Issue: Getting validation errors like merchantName is requiredSolution:
  • Ensure ALL required fields from original onboarding are included
  • Don’t just send changed fields - send complete data
  • Use retrieve endpoint to get current data first
  • Validate against the same rules as initial onboarding

Field Validation Reference

  • First/Middle/Last Names: 1-100 chars, Unicode letters, spaces, hyphens, apostrophes
  • Email: Valid email format, max 100 chars
  • TIN: Numbers only, max 20 chars
  • Postal Code: 4-10 digits, numbers only
  • Contact Number: Numbers only, max 30 chars
  • SSS: Exactly 10 digits

Next Steps

Authorizations

Authorization
string
header
required

JWT Bearer token authentication

Path Parameters

refNo
string<uuid>
required

The onboarding reference number (UUID v4 format)

Body

application/json
merchantName
string
required

Trading name or DBA (Doing Business As) name

Maximum string length: 500
modeOfPayments
enum<string>[]
required

List of accepted payment modes

Minimum array length: 1
Available options:
CREDIT_CARD,
DEBIT_CARD,
GCASH,
GRABPAY,
PAYMAYA,
BANK_TRANSFER
currency
enum<string>
required

Primary currency for transactions

Available options:
PHP,
USD
tin
string
required

Tax Identification Number

Maximum string length: 20
industry
string
required

Business industry category

Maximum string length: 200
serviceDescription
string
required

Description of services or products offered

isBrickAndMortarStore
boolean
required

Whether the business has a physical store location

address
object
required
representatives
object
required
banks
object[]
required

List of bank accounts for settlement

Required array length: 1 - 2 elements

Legal registered name of the business (required for non-STARTER types)

Maximum string length: 500
businessHandle
string

Unique business handle/slug for payment links (required for non-STARTER types)

incorporators
object[]

List of business incorporators (for non-STARTER types)

Required array length: 1 - 5 elements
signatories
object[]

List of authorized signatories

Required array length: 1 - 5 elements
websites
object

Response

Onboarding data updated successfully

onboardingStatus
enum<string>

New status after update (PENDING for regular users, APPROVED unchanged for Super Admins)

Available options:
PENDING,
APPROVED
onboardingReferenceNumber
string<uuid>

The onboarding reference number (unchanged)