> ## 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.

# Retrieve Onboarding Data

> Retrieve complete merchant onboarding data by reference number

## Overview

Retrieves the complete onboarding data for a merchant using the onboarding reference number. This endpoint returns all information submitted during the onboarding process, including business details, representatives, bank accounts, and current approval status.

<Info>
  **Use case:** Check the status of a merchant's onboarding application and retrieve all submitted information for review or updates.
</Info>

## Authentication

This endpoint requires JWT Bearer Token authentication.

```bash theme={null}
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

<Warning>
  **Authorization Required:** The authenticated user must be the owner of the onboarding record. Only the user who created the onboarding record can retrieve it.
</Warning>

## Path Parameters

<ParamField path="refNo" type="string" required>
  The onboarding reference number (UUID v4 format)

  **Format:** Valid UUID v4

  **Example:** `"550e8400-e29b-41d4-a716-446655440000"`

  <Note>
    This is the `referenceNumber` returned when you successfully submit an onboarding request via the [Onboard Merchant](/api-reference/onboarding/onboard-merchant) endpoint.
  </Note>
</ParamField>

## Response

### Success Response

**Status Code:** `200 OK`

<ResponseField name="onboardingStatus" type="string" required>
  Current status of the merchant's onboarding application

  **Values:**

  * `NEW`: Merchant completed onboarding, awaiting initial approval
  * `PENDING`: Merchant updated form after decline, awaiting re-approval
  * `APPROVED`: Merchant has been approved
  * `DECLINED`: Merchant was declined and needs to update their form

  **Example:** `"NEW"`
</ResponseField>

<ResponseField name="onboardingReferenceNumber" type="string" required>
  Unique identifier for the onboarding record

  **Format:** UUID v4

  **Example:** `"550e8400-e29b-41d4-a716-446655440000"`
</ResponseField>

<ResponseField name="businessType" type="string" required>
  Type of business entity

  **Values:** `STARTER`, `SOLE_PROPRIETOR`, `PARTNERSHIP`, `CORPORATION`

  **Example:** `"CORPORATION"`
</ResponseField>

<ResponseField name="legalName" type="string">
  Legal registered name of the business

  **Example:** `"Acme Corporation Inc."`
</ResponseField>

<ResponseField name="merchantName" type="string" required>
  Trading name or DBA (Doing Business As) name

  **Example:** `"Acme Store"`
</ResponseField>

<ResponseField name="modeOfPayments" type="array" required>
  List of accepted payment modes

  **Example:** `["ECOM", "QRPH", "PAYMENT_LINK"]`
</ResponseField>

<ResponseField name="currency" type="string" required>
  Primary currency for transactions

  **Example:** `"PHP"`
</ResponseField>

<ResponseField name="tin" type="string" required>
  Tax Identification Number

  **Example:** `"123-456-789-000"`
</ResponseField>

<ResponseField name="industry" type="string" required>
  Business industry category

  **Example:** `"Retail"`
</ResponseField>

<ResponseField name="serviceDescription" type="string" required>
  Description of services or products offered

  **Example:** `"Online retail store selling electronics and gadgets"`
</ResponseField>

<ResponseField name="businessHandle" type="string" required>
  Unique business handle/slug for payment links

  **Example:** `"acme-store"`
</ResponseField>

<ResponseField name="isBrickAndMortarStore" type="boolean" required>
  Whether the business has a physical store location

  **Example:** `true`
</ResponseField>

<ResponseField name="address" type="object" required>
  Business address information

  <Expandable title="Address Properties">
    <ResponseField name="address.office" type="object" required>
      Main office location with contact number

      **Properties:** `city`, `line1`, `buildingNameAndNumber`, `state`, `postalCode`, `barangay`, `contactNumber`
    </ResponseField>

    <ResponseField name="address.registered" type="object">
      Registered business address (if different from office)

      **Properties:** `city`, `line1`, `buildingNameAndNumber`, `state`, `postalCode`, `barangay`, `contactNumber`
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="representatives" type="object" required>
  Authorized representatives

  <Expandable title="Representatives Properties">
    <ResponseField name="representatives.authorized" type="object" required>
      Primary authorized representative

      **Properties:** `firstName`, `middleName`, `lastName`, `emailAddress`, `contactNumber`, `dateOfBirth`, `tin`, `sss`, `position`, `mothersMaidenName`, `gender`
    </ResponseField>

    <ResponseField name="representatives.escalation" type="object">
      Escalation contact (optional)

      **Properties:** `firstName`, `middleName`, `lastName`, `emailAddress`, `contactNumber`, `dateOfBirth`, `tin`, `sss`, `position`
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="banks" type="array" required>
  List of bank accounts for settlement

  <Expandable title="Bank Account Properties">
    <ResponseField name="banks[].accountDepositType" type="string" required>
      Type of deposit account: `BANK`, `GCASH`, `PAYMAYA`, `NO_ACCOUNT`
    </ResponseField>

    <ResponseField name="banks[].bankName" type="string">
      Name of the bank
    </ResponseField>

    <ResponseField name="banks[].accountName" type="string">
      Name on the bank account
    </ResponseField>

    <ResponseField name="banks[].accountNumber" type="string">
      Bank account number

      <Warning>
        **Security Note:** Account numbers may be masked (showing only last 4 digits) depending on user role. Full numbers visible to Super Admins, Settlement, Checker roles, and account owner.
      </Warning>
    </ResponseField>

    <ResponseField name="banks[].currency" type="string">
      Currency of the bank account
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="incorporators" type="array">
  List of business incorporators (not applicable for STARTER business type)

  **Properties:** `firstName`, `middleName`, `lastName`, `emailAddress`, `contactNumber`, `dateOfBirth`, `address`
</ResponseField>

<ResponseField name="signatories" type="array">
  List of authorized signatories

  **Properties:** `firstName`, `middleName`, `lastName`, `position`
</ResponseField>

<ResponseField name="websites" type="object">
  Business online presence

  **Properties:** `businessWebsiteUrl`, `isBusinessWebsiteUnderDevelopment`, `facebookUrl`, `twitterUrl`, `instagramUrl`, `tiktokUrl`
</ResponseField>

<ResponseField name="dateCreated" type="string" required>
  Timestamp when the onboarding record was created

  **Format:** ISO 8601

  **Example:** `"2024-01-15T10:30:00Z"`
</ResponseField>

<ResponseField name="dateUpdated" type="string">
  Timestamp of the last status update

  **Format:** ISO 8601

  **Example:** `"2024-01-20T14:45:00Z"`
</ResponseField>

<ResponseField name="declinedReason" type="string">
  Reason for decline (only present when status is DECLINED)

  **Example:** `"Missing required documents"`
</ResponseField>

### Error Responses

<AccordionGroup>
  <Accordion title="400 Bad Request - Invalid Reference Number Format">
    **Status Code:** `400`

    ```json theme={null}
    {
      "statusCode": 400,
      "message": "Invalid onboarding reference number format",
      "error": "Bad Request",
      "details": {
        "refNumReceived": "invalid-uuid-format"
      }
    }
    ```

    **Cause:** The reference number provided is not a valid UUID v4 format

    **Solution:** Ensure the reference number is a valid UUID v4 string
  </Accordion>

  <Accordion title="400 Bad Request - Record Does Not Exist">
    **Status Code:** `400`

    ```json theme={null}
    {
      "statusCode": 400,
      "message": "Onboarding record does not exist",
      "error": "Bad Request"
    }
    ```

    **Cause:** No onboarding record found with the provided reference number

    **Solution:** Verify the reference number is correct and the onboarding record exists
  </Accordion>

  <Accordion title="400 Bad Request - Reference Number Mismatch">
    **Status Code:** `400`

    ```json theme={null}
    {
      "statusCode": 400,
      "message": "Onboarding reference number mismatch",
      "error": "Bad Request",
      "details": {
        "refNumReceived": "550e8400-e29b-41d4-a716-446655440000"
      }
    }
    ```

    **Cause:** The authenticated user is not authorized to access this onboarding record

    **Solution:** Ensure you're using the correct JWT token for the account that owns this onboarding record
  </Accordion>

  <Accordion title="400 Bad Request - Failed to Retrieve Representatives">
    **Status Code:** `400`

    ```json theme={null}
    {
      "statusCode": 400,
      "message": "Failed to retrieve authorized representatives",
      "error": "Bad Request"
    }
    ```

    **Cause:** Database error retrieving representative information

    **Solution:** Retry the request. If the issue persists, contact support
  </Accordion>

  <Accordion title="401 Unauthorized">
    **Status Code:** `401`

    ```json theme={null}
    {
      "statusCode": 401,
      "message": "Account not found",
      "error": "Unauthorized"
    }
    ```

    **Cause:** Invalid or missing JWT Bearer token, or account associated with token doesn't exist

    **Solution:**

    * Verify the Authorization header contains a valid JWT token
    * Ensure the token hasn't expired
    * Confirm the account exists in the system
  </Accordion>
</AccordionGroup>

<RequestExample>
  ```bash cURL theme={null}
  # Set your Bearer token and reference number
  TOKEN="your_jwt_bearer_token_here"
  REF_NO="550e8400-e29b-41d4-a716-446655440000"

  curl -X GET "https://kyc.sbx.moduluslabs.io/v2/onboard/$REF_NO" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Accept: application/json"
  ```

  ```javascript Node.js theme={null}
  const axios = require('axios');

  const BEARER_TOKEN = process.env.BEARER_TOKEN;
  const REFERENCE_NUMBER = '550e8400-e29b-41d4-a716-446655440000';

  async function retrieveOnboardingData(refNo) {
    try {
      const response = await axios.get(
        `https://kyc.sbx.moduluslabs.io/v2/onboard/${refNo}`,
        {
          headers: {
            'Authorization': `Bearer ${BEARER_TOKEN}`,
            'Accept': 'application/json'
          }
        }
      );

      console.log(' Onboarding data retrieved successfully');
      console.log('Status:', response.data.onboardingStatus);
      console.log('Merchant Name:', response.data.merchantName);
      console.log('Reference Number:', response.data.onboardingReferenceNumber);

      if (response.data.declinedReason) {
        console.log('  Declined Reason:', response.data.declinedReason);
      }

      return response.data;

    } catch (error) {
      if (error.response?.status === 401) {
        console.error('  Unauthorized. Check your Bearer token.');
      } else if (error.response?.status === 400) {
        console.error('  Bad Request:', error.response.data.message);
      } else {
        console.error(' Request failed:', error.response?.data || error.message);
      }
      throw error;
    }
  }

  // Usage
  retrieveOnboardingData(REFERENCE_NUMBER);
  ```

  ```python Python theme={null}
  import os
  import requests

  BEARER_TOKEN = os.getenv('BEARER_TOKEN')
  REFERENCE_NUMBER = '550e8400-e29b-41d4-a716-446655440000'

  def retrieve_onboarding_data(ref_no):
      """Retrieve onboarding data by reference number"""
      try:
          response = requests.get(
              f'https://kyc.sbx.moduluslabs.io/v2/onboard/{ref_no}',
              headers={
                  'Authorization': f'Bearer {BEARER_TOKEN}',
                  'Accept': 'application/json'
              }
          )

          response.raise_for_status()
          data = response.json()

          print(' Onboarding data retrieved successfully')
          print(f"Status: {data['onboardingStatus']}")
          print(f"Merchant Name: {data['merchantName']}")
          print(f"Reference Number: {data['onboardingReferenceNumber']}")

          if data.get('declinedReason'):
              print(f"  Declined Reason: {data['declinedReason']}")

          return data

      except requests.exceptions.HTTPError as e:
          if e.response.status_code == 401:
              print('  Unauthorized. Check your Bearer token.')
          elif e.response.status_code == 400:
              print(f"  Bad Request: {e.response.json().get('message')}")
          else:
              print(f' Request failed: {e.response.text}')
          raise

  if __name__ == '__main__':
      retrieve_onboarding_data(REFERENCE_NUMBER)
  ```

  ```php PHP theme={null}
  <?php
  require 'vendor/autoload.php';

  use GuzzleHttp\Client;
  use GuzzleHttp\Exception\RequestException;

  $bearerToken = getenv('BEARER_TOKEN');
  $referenceNumber = '550e8400-e29b-41d4-a716-446655440000';

  function retrieveOnboardingData($refNo) {
      global $bearerToken;

      try {
          $client = new Client();
          $response = $client->get(
              "https://kyc.sbx.moduluslabs.io/v2/onboard/$refNo",
              [
                  'headers' => [
                      'Authorization' => 'Bearer ' . $bearerToken,
                      'Accept' => 'application/json'
                  ]
              ]
          );

          $data = json_decode($response->getBody(), true);

          echo " Onboarding data retrieved successfully\n";
          echo "Status: " . $data['onboardingStatus'] . "\n";
          echo "Merchant Name: " . $data['merchantName'] . "\n";
          echo "Reference Number: " . $data['onboardingReferenceNumber'] . "\n";

          if (isset($data['declinedReason'])) {
              echo "  Declined Reason: " . $data['declinedReason'] . "\n";
          }

          return $data;

      } catch (RequestException $e) {
          if ($e->hasResponse()) {
              $statusCode = $e->getResponse()->getStatusCode();
              if ($statusCode === 401) {
                  echo "  Unauthorized. Check your Bearer token.\n";
              } elseif ($statusCode === 400) {
                  $body = json_decode($e->getResponse()->getBody(), true);
                  echo "  Bad Request: " . $body['message'] . "\n";
              } else {
                  echo " Request failed: " . $e->getMessage() . "\n";
                  echo $e->getResponse()->getBody() . "\n";
              }
          } else {
              echo " Request failed: " . $e->getMessage() . "\n";
          }
          throw $e;
      }
  }

  retrieveOnboardingData($referenceNumber);
  ?>
  ```

  ```java Java theme={null}
  import com.google.gson.Gson;
  import okhttp3.*;

  import java.io.IOException;

  public class RetrieveOnboardingData {
      private static final String BEARER_TOKEN = System.getenv("BEARER_TOKEN");
      private static final String REFERENCE_NUMBER = "550e8400-e29b-41d4-a716-446655440000";
      private static final String API_URL = "https://kyc.sbx.moduluslabs.io/v2/onboard/";

      public static void retrieveOnboardingData(String refNo) throws IOException {
          OkHttpClient client = new OkHttpClient();

          Request request = new Request.Builder()
                  .url(API_URL + refNo)
                  .header("Authorization", "Bearer " + BEARER_TOKEN)
                  .header("Accept", "application/json")
                  .get()
                  .build();

          try (Response response = client.newCall(request).execute()) {
              String responseBody = response.body().string();

              if (response.isSuccessful()) {
                  Gson gson = new Gson();
                  OnboardingData data = gson.fromJson(responseBody, OnboardingData.class);

                  System.out.println(" Onboarding data retrieved successfully");
                  System.out.println("Status: " + data.onboardingStatus);
                  System.out.println("Merchant Name: " + data.merchantName);
                  System.out.println("Reference Number: " + data.onboardingReferenceNumber);

                  if (data.declinedReason != null) {
                      System.out.println("  Declined Reason: " + data.declinedReason);
                  }
              } else if (response.code() == 401) {
                  System.out.println("  Unauthorized. Check your Bearer token.");
              } else if (response.code() == 400) {
                  System.out.println("  Bad Request: " + responseBody);
              } else {
                  System.out.println(" Request failed: HTTP " + response.code());
                  System.out.println("Details: " + responseBody);
              }
          }
      }

      public static void main(String[] args) {
          try {
              retrieveOnboardingData(REFERENCE_NUMBER);
          } catch (IOException e) {
              System.err.println(" Error: " + e.getMessage());
              e.printStackTrace();
          }
      }

      // Response model
      static class OnboardingData {
          String onboardingStatus;
          String onboardingReferenceNumber;
          String merchantName;
          String declinedReason;
      }
  }
  ```

  ```go Go theme={null}
  package main

  import (
  	"encoding/json"
  	"fmt"
  	"io"
  	"net/http"
  	"os"
  	"time"
  )

  const (
  	apiURL          = "https://kyc.sbx.moduluslabs.io/v2/onboard/"
  	referenceNumber = "550e8400-e29b-41d4-a716-446655440000"
  )

  type OnboardingData struct {
  	OnboardingStatus          string `json:"onboardingStatus"`
  	OnboardingReferenceNumber string `json:"onboardingReferenceNumber"`
  	MerchantName              string `json:"merchantName"`
  	DeclinedReason            string `json:"declinedReason,omitempty"`
  }

  func retrieveOnboardingData(refNo string) error {
  	bearerToken := os.Getenv("BEARER_TOKEN")

  	req, err := http.NewRequest("GET", apiURL+refNo, nil)
  	if err != nil {
  		return fmt.Errorf("failed to create request: %w", err)
  	}

  	req.Header.Set("Authorization", "Bearer "+bearerToken)
  	req.Header.Set("Accept", "application/json")

  	client := &http.Client{Timeout: 30 * time.Second}
  	resp, err := client.Do(req)
  	if err != nil {
  		return fmt.Errorf("request failed: %w", err)
  	}
  	defer resp.Body.Close()

  	body, err := io.ReadAll(resp.Body)
  	if err != nil {
  		return fmt.Errorf("failed to read response: %w", err)
  	}

  	if resp.StatusCode == http.StatusOK {
  		var data OnboardingData
  		if err := json.Unmarshal(body, &data); err != nil {
  			return fmt.Errorf("failed to parse response: %w", err)
  		}

  		fmt.Println(" Onboarding data retrieved successfully")
  		fmt.Printf("Status: %s\n", data.OnboardingStatus)
  		fmt.Printf("Merchant Name: %s\n", data.MerchantName)
  		fmt.Printf("Reference Number: %s\n", data.OnboardingReferenceNumber)

  		if data.DeclinedReason != "" {
  			fmt.Printf("  Declined Reason: %s\n", data.DeclinedReason)
  		}

  		return nil
  	} else if resp.StatusCode == http.StatusUnauthorized {
  		fmt.Println("  Unauthorized. Check your Bearer token.")
  		return fmt.Errorf("unauthorized")
  	} else if resp.StatusCode == http.StatusBadRequest {
  		fmt.Printf("  Bad Request: %s\n", string(body))
  		return fmt.Errorf("bad request")
  	}

  	fmt.Printf(" Request failed: HTTP %d\n", resp.StatusCode)
  	fmt.Printf("Details: %s\n", string(body))
  	return fmt.Errorf("request failed with status %d", resp.StatusCode)
  }

  func main() {
  	if err := retrieveOnboardingData(referenceNumber); err != nil {
  		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
  		os.Exit(1)
  	}
  }
  ```

  ```csharp C# / .NET theme={null}
  using System;
  using System.Net.Http;
  using System.Net.Http.Headers;
  using System.Text.Json;
  using System.Threading.Tasks;

  class Program
  {
      static async Task Main(string[] args)
      {
          await RetrieveOnboardingData("550e8400-e29b-41d4-a716-446655440000");
      }

      static async Task RetrieveOnboardingData(string refNo)
      {
          var bearerToken = Environment.GetEnvironmentVariable("BEARER_TOKEN");

          if (string.IsNullOrEmpty(bearerToken))
          {
              Console.WriteLine(" Error: BEARER_TOKEN environment variable not set");
              return;
          }

          try
          {
              using var client = new HttpClient();
              client.DefaultRequestHeaders.Authorization =
                  new AuthenticationHeaderValue("Bearer", bearerToken);
              client.DefaultRequestHeaders.Accept.Add(
                  new MediaTypeWithQualityHeaderValue("application/json"));

              var response = await client.GetAsync(
                  $"https://kyc.sbx.moduluslabs.io/v2/onboard/{refNo}"
              );

              var responseBody = await response.Content.ReadAsStringAsync();

              if (response.IsSuccessStatusCode)
              {
                  var data = JsonSerializer.Deserialize<OnboardingData>(
                      responseBody,
                      new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
                  );

                  Console.WriteLine(" Onboarding data retrieved successfully");
                  Console.WriteLine($"Status: {data.OnboardingStatus}");
                  Console.WriteLine($"Merchant Name: {data.MerchantName}");
                  Console.WriteLine($"Reference Number: {data.OnboardingReferenceNumber}");

                  if (!string.IsNullOrEmpty(data.DeclinedReason))
                  {
                      Console.WriteLine($"  Declined Reason: {data.DeclinedReason}");
                  }
              }
              else if ((int)response.StatusCode == 401)
              {
                  Console.WriteLine("  Unauthorized. Check your Bearer token.");
              }
              else if ((int)response.StatusCode == 400)
              {
                  Console.WriteLine($"  Bad Request: {responseBody}");
              }
              else
              {
                  Console.WriteLine($" Request failed: HTTP {(int)response.StatusCode}");
                  Console.WriteLine($"Details: {responseBody}");
              }
          }
          catch (HttpRequestException e)
          {
              Console.WriteLine($" Request failed: {e.Message}");
          }
          catch (Exception e)
          {
              Console.WriteLine($" Error: {e.Message}");
          }
      }
  }

  public class OnboardingData
  {
      public string OnboardingStatus { get; set; }
      public string OnboardingReferenceNumber { get; set; }
      public string MerchantName { get; set; }
      public string DeclinedReason { get; set; }
  }
  ```
</RequestExample>

## Onboarding Status Flow

<Steps>
  <Step title="NEW">
    Merchant has completed the onboarding form and submitted it for initial review. Awaiting admin approval.
  </Step>

  <Step title="DECLINED (Optional)">
    Admin reviewed the application and declined it. The `declinedReason` field contains the reason for rejection. Merchant needs to update their information.
  </Step>

  <Step title="PENDING (Optional)">
    Merchant has updated their form after being declined and resubmitted for review. Awaiting admin re-approval.
  </Step>

  <Step title="APPROVED">
    Admin has approved the merchant's onboarding application. Merchant can now process transactions.
  </Step>
</Steps>

## Bank Account Masking

<Info>
  **Security Feature:** Bank account numbers are masked for security based on user roles.
</Info>

**Full account numbers visible to:**

* Super Admins
* Settlement role users
* Checker role users
* The account owner (authenticated user who created the onboarding record)

**Other users see:** `********1234` (only last 4 digits visible)

## Use Cases

<CardGroup cols={2}>
  <Card title="Check Application Status" icon="clipboard-check">
    Monitor the approval status of your onboarding application
  </Card>

  <Card title="Review Submitted Data" icon="eye">
    Verify all information submitted during onboarding
  </Card>

  <Card title="Handle Declined Applications" icon="triangle-exclamation">
    Check the decline reason and prepare updated information
  </Card>

  <Card title="Retrieve for Updates" icon="pen-to-square">
    Get current data before submitting corrections or updates
  </Card>
</CardGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Save the Reference Number" icon="bookmark">
    Always save the `referenceNumber` returned from the Onboard Merchant endpoint. You'll need it to check status and retrieve data later.

    ```javascript theme={null}
    // Save this from onboarding response
    const referenceNumber = onboardingResponse.referenceNumber;
    // Store in database or secure storage
    ```
  </Accordion>

  <Accordion title="Poll for Status Updates" icon="arrows-rotate">
    Implement polling to check for status changes if you need real-time updates:

    ```javascript theme={null}
    async function pollOnboardingStatus(refNo) {
      const interval = setInterval(async () => {
        const data = await retrieveOnboardingData(refNo);

        if (data.onboardingStatus === 'APPROVED') {
          console.log(' Onboarding approved!');
          clearInterval(interval);
        } else if (data.onboardingStatus === 'DECLINED') {
          console.log(' Onboarding declined:', data.declinedReason);
          clearInterval(interval);
        }
      }, 60000); // Check every minute
    }
    ```

    <Tip>
      Consider implementing exponential backoff for polling to avoid rate limiting.
    </Tip>
  </Accordion>

  <Accordion title="Handle Declined Applications" icon="rotate">
    When status is `DECLINED`, present the decline reason to the user and guide them to update their information:

    ```javascript theme={null}
    if (data.onboardingStatus === 'DECLINED') {
      // Show decline reason to user
      alert(`Application declined: ${data.declinedReason}`);
      // Redirect to update form
      window.location.href = '/update-onboarding';
    }
    ```
  </Accordion>

  <Accordion title="Cache Response Data" icon="database">
    Cache the response to reduce API calls:

    ```javascript theme={null}
    const CACHE_TTL = 300000; // 5 minutes
    let cachedData = null;
    let cacheTimestamp = 0;

    async function getCachedOnboardingData(refNo) {
      const now = Date.now();

      if (cachedData && (now - cacheTimestamp) < CACHE_TTL) {
        return cachedData;
      }

      cachedData = await retrieveOnboardingData(refNo);
      cacheTimestamp = now;
      return cachedData;
    }
    ```
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Reference Number Mismatch Error" icon="triangle-exclamation">
    **Error:** `Onboarding reference number mismatch`

    **Cause:** You're trying to access an onboarding record that doesn't belong to your account

    **Solution:**

    * Verify you're using the correct JWT token for the account that created this onboarding record
    * Each onboarding record can only be accessed by the account that created it
    * Super Admins may need special permissions to access other accounts' records
  </Accordion>

  <Accordion title="Invalid UUID Format" icon="exclamation">
    **Error:** `Invalid onboarding reference number format`

    **Solution:**

    * Ensure the reference number is a valid UUID v4 format
    * Example valid format: `550e8400-e29b-41d4-a716-446655440000`
    * Check for extra spaces or incorrect characters
  </Accordion>

  <Accordion title="Record Not Found" icon="search">
    **Error:** `Onboarding record does not exist`

    **Possible Causes:**

    * The reference number is incorrect
    * The onboarding record was deleted
    * You're using a sandbox reference number in production (or vice versa)

    **Solution:**

    * Double-check the reference number
    * Verify you're using the correct environment (sandbox vs production)
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Onboard Merchant" icon="plus" href="/api-reference/onboarding/onboard-merchant">
    Create a new merchant onboarding record
  </Card>

  <Card title="Create Account" icon="user-plus" href="/api-reference/onboarding/create-account">
    Create an account before onboarding
  </Card>

  <Card title="Authentication Guide" icon="key" href="/docs/onboarding/authentication">
    Learn about JWT token authentication
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/docs/errors">
    Handle API errors properly
  </Card>
</CardGroup>


## OpenAPI

````yaml GET /v2/onboard/{refNo}
openapi: 3.1.0
info:
  title: Modulus Labs Onboarding API
  description: API for merchant onboarding, KYC verification, and account management
  version: 2.0.0
servers:
  - url: https://kyc.sbx.moduluslabs.io
    description: Sandbox
security: []
paths:
  /v2/onboard/{refNo}:
    get:
      tags:
        - Onboarding
      summary: Retrieve Onboarding Data
      description: >-
        Retrieve the complete onboarding data for a merchant using the
        onboarding reference number.
      operationId: retrieveOnboardingData
      parameters:
        - $ref: '#/components/parameters/RefNoParam'
      responses:
        '200':
          description: Onboarding data retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OnboardingDataResponse'
        '400':
          description: Bad Request - Invalid reference number or record does not exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - bearerAuth: []
components:
  parameters:
    RefNoParam:
      name: refNo
      in: path
      required: true
      description: The onboarding reference number (UUID v4 format)
      schema:
        type: string
        format: uuid
      example: 550e8400-e29b-41d4-a716-446655440000
  schemas:
    OnboardingDataResponse:
      type: object
      properties:
        onboardingStatus:
          type: string
          enum:
            - NEW
            - PENDING
            - APPROVED
            - DECLINED
        onboardingReferenceNumber:
          type: string
          format: uuid
        merchantName:
          type: string
        legalName:
          type: string
        businessHandle:
          type: string
        modeOfPayments:
          type: array
          items:
            type: string
        currency:
          type: string
        tin:
          type: string
        industry:
          type: string
        serviceDescription:
          type: string
        isBrickAndMortarStore:
          type: boolean
        address:
          $ref: '#/components/schemas/BusinessAddress'
        representatives:
          $ref: '#/components/schemas/Representatives'
        banks:
          type: array
          items:
            $ref: '#/components/schemas/BankAccount'
        dateCreated:
          type: string
          format: date-time
        dateUpdated:
          type: string
          format: date-time
          nullable: true
        declinedReason:
          type: string
          nullable: true
    ErrorResponse:
      type: object
      properties:
        statusCode:
          type: integer
          description: HTTP status code
        message:
          type: string
          description: Error message
        error:
          type: string
          description: Error type
        details:
          type: object
          description: Additional error details
    BusinessAddress:
      type: object
      required:
        - office
      properties:
        office:
          $ref: '#/components/schemas/Address'
        registered:
          $ref: '#/components/schemas/Address'
    Representatives:
      type: object
      required:
        - authorized
      properties:
        authorized:
          $ref: '#/components/schemas/AuthorizedRepresentative'
        escalation:
          $ref: '#/components/schemas/EscalationRepresentative'
    BankAccount:
      type: object
      required:
        - accountDepositType
        - currency
      properties:
        accountDepositType:
          type: string
          enum:
            - BANK
            - PAYMAYA
            - GCASH
            - NO_ACCOUNT
          description: Type of deposit account
        accountType:
          type: string
          enum:
            - SAVINGS
            - CHECKING_CURRENT
          description: Type of bank account (required when accountDepositType is BANK)
        bankName:
          type: string
          maxLength: 500
          description: >-
            Name of the bank (required when accountDepositType is not
            NO_ACCOUNT)
        accountName:
          type: string
          maxLength: 500
          description: Name on the bank account
        accountNumber:
          type: string
          maxLength: 500
          description: Bank account number (will be encrypted)
        currency:
          type: string
          enum:
            - PHP
            - USD
          description: Currency of the bank account
        preferredSettlementRail:
          type: string
          enum:
            - instapay
            - pesonet
          description: Preferred settlement rail for fund transfers
        bankCode:
          type: string
          pattern: ^[A-Z0-9]{8,11}$
          description: SWIFT/BIC code
    Address:
      type: object
      required:
        - city
        - line1
        - state
        - postalCode
        - contactNumber
        - barangay
      properties:
        city:
          type: string
          maxLength: 100
          description: City
        line1:
          type: string
          maxLength: 64
          description: Street address
        buildingNameAndNumber:
          type: string
          maxLength: 200
          description: Building name and number
        state:
          type: string
          maxLength: 64
          description: Province/State
        postalCode:
          type: string
          pattern: ^\d{4,10}$
          description: Postal code (4-10 digits)
        contactNumber:
          type: string
          pattern: ^\d+$
          maxLength: 30
          description: Contact number (digits only)
        barangay:
          type: string
          maxLength: 200
          description: Barangay
    AuthorizedRepresentative:
      type: object
      required:
        - firstName
        - lastName
        - emailAddress
        - contactNumber
        - dateOfBirth
        - position
      properties:
        firstName:
          type: string
          maxLength: 100
        middleName:
          type: string
          maxLength: 100
        lastName:
          type: string
          maxLength: 100
        emailAddress:
          type: string
          format: email
          maxLength: 100
        contactNumber:
          type: string
          pattern: ^\d+$
          maxLength: 30
        dateOfBirth:
          type: string
          format: date
          description: Date of birth (ISO 8601 date format)
        position:
          type: string
          maxLength: 100
          description: Job position/title
        tin:
          type: string
          pattern: ^\d+$
          maxLength: 20
        sss:
          type: string
          pattern: ^\d{10}$
          description: SSS number (exactly 10 digits)
        mothersMaidenName:
          type: string
          maxLength: 255
        gender:
          type: string
          enum:
            - MALE
            - FEMALE
    EscalationRepresentative:
      type: object
      properties:
        firstName:
          type: string
          maxLength: 100
        lastName:
          type: string
          maxLength: 100
        emailAddress:
          type: string
          format: email
        contactNumber:
          type: string
          pattern: ^\d+$
        dateOfBirth:
          type: string
          format: date
        tin:
          type: string
          pattern: ^\d{9}$
        sss:
          type: string
          pattern: ^\d{10}$
        position:
          type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT Bearer token authentication

````