> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.credit.aarthiklabs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.credit.aarthiklabs.com/_mcp/server.

# Start Dedupe

POST https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/{borrowerProviderID}/journey/dedupe
Content-Type: application/json

Begin with a simple check to understand whether a borrower can proceed with participating lending partners. Share the borrower's identifiers in the format configured for your application—hashed or unhashed—and Aarthik Labs starts the Dedupe check.

This is an optional first step. The response gives you a journey ID to carry through the application. Use **Fetch Dedupe Results** to view the outcome, then continue with Eligibility or **Create A Journey** using the same ID.

Reference: https://docs.credit.aarthiklabs.com/api-reference/hybrid-experience/business-loan/start-hybrid-business-loan-dedupe

## Authentication

- `Authorization` header (bearer token, required) — Send `Authorization: Bearer <PLATFORM_API_KEY>` from a trusted back-end.

## Servers

- `https://credit.aarthiklabs.com` (Production, default)
- `https://preprod.credit.aarthiklabs.com` (PreProduction)

## Request

### Path parameters

- `borrowerProviderID` (string, required) — Stable borrower identity from the partner system. Keep a 1:1 mapping between the borrower and `borrowerProviderID` across sessions and application attempts to preserve resume, history, and post-disbursal continuity.

### Query parameters

- `journeyID` (string, optional) — Omit to create a journey. Supply the journeyID returned by Dedupe or Eligibility to continue the same borrower journey. Keep borrowerProviderID unchanged. An invalid, expired, unknown or unauthorized ID must not create a replacement journey.

### Headers

- `Idempotency-Key` (string, optional) — Start-attempt retry key. Use a fresh key for each new application attempt. Reuse the same key only when retrying the same Start request after a timeout or temporary failure. If omitted, the platform creates a fresh non-idempotent attempt with a server-generated internal key for compatibility; retries without a client key can create duplicate attempts.
- `x-correlation-id` (string, optional) — Optional caller-supplied trace identifier. When omitted, the API generates one and mirrors it as `correlation_id`.

### Body (application/json)

This endpoint expects a HybridBusinessDedupeRequest.

- `journeyType` ("BUSINESS_LOAN", required)
- `identifiers` (HybridBusinessDedupeIdentifiers, required) — Provide at least one of pan or mobileNumber. The identifier representation is configured for your application by Aarthik Labs; do not send a mode flag. Example hashes are synthetic opaque values, not an algorithm specification.

## Response

### 202

Dedupe operation accepted. Store data.journeyID, then call Fetch Dedupe Results. Polling guidance is returned by the Fetch Results API, not this response.

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (HybridBusinessDedupeStartData, required)
- `error` (any, required)

## Errors

### 400 Bad Request Error

Request body or path validation failed.

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (any, required)
- `error` (HybridError, required)

### 401 Unauthorized Error

Missing or invalid platform API key.

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (any, required)
- `error` (HybridError, required)

### 403 Forbidden Error

Business Hybrid bundle creation is disabled for the authenticated application. Exact retries of an existing bundle remain resumable.

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (any, required)
- `error` (HybridError, required)

### 409 Conflict Error

The current journey or offer state does not allow the requested transition.

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (any, required)
- `error` (HybridError, required)

### 424 Failed Dependency Error

No compatible Business Loan discovery target is configured for the authenticated application scope.

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (any, required)
- `error` (HybridError, required)

### 429 Too Many Requests Error

Too many requests. For offer polling, retry at the returned `polling.nextPoll` timestamp.

- `StartHybridBusinessLoanDedupeRequestTooManyRequestsError`
  - HybridErrorResponse: HybridErrorResponse
  - HybridOfferPollingRateLimitedResponse: HybridOfferPollingRateLimitedResponse

### 500 Internal Server Error

Temporary upstream or platform failure.

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (any, required)
- `error` (HybridError, required)

### 503 Service Unavailable Error

Temporary upstream or platform failure.

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (any, required)
- `error` (HybridError, required)

## Types

### HybridBusinessDedupeIdentifiers

Provide at least one of pan or mobileNumber. The identifier representation is configured for your application by Aarthik Labs; do not send a mode flag. Example hashes are synthetic opaque values, not an algorithm specification.

- `pan` (string, optional)
- `mobileNumber` (string, optional)

### HybridBusinessDedupeStartData

- `journeyID` (string, required)
- `stage` ("DEDUPE", required)
- `status` (enum, required) — Journey-level outcome: PENDING if any lender is pending; otherwise CLEAR if any lender is CLEAR or SKIPPED; otherwise NOT_CLEAR. ERROR counts as negative. Lender-level statuses remain unchanged.
  - Allowed values: `CLEAR`, `NOT_CLEAR`, `PENDING`
- `lenders` (list of HybridBusinessDedupeLenderResult, required)

### HybridError

- `code` (enum, required)
  - Allowed values: `VALIDATION_FAILED`, `AUTH_INVALID_API_KEY`, `AUTH_INVALID_SESSION`, `ACCESS_SCOPE_MISMATCH`, `RESOURCE_NOT_FOUND`, `OFFER_LOCK_CONFLICT`, `STATE_PRECONDITION_FAILED`, `OFFER_POLL_RATE_LIMITED`, `HYBRID_JOURNEY_NOT_READY`, `RATE_LIMITED`, `UPSTREAM_TEMPORARY_FAILURE`
- `message` (string, required)
- `retryable` (boolean, required) — Whether retrying the same operation can make progress. A persisted final primary-form failure is not retryable, including HTTP 500; reconcile the accepted operation before any resubmission. Correct invalid input before retrying validation failures.
- `details` (map from string to any, required, nullable)

### HybridErrorResponse

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (any, required)
- `error` (HybridError, required)

### HybridOfferPollingRateLimitedResponse

- `request_id` (string, required)
- `correlation_id` (string, required)
- `timestamp` (datetime, required)
- `data` (HybridOfferPollingRateLimitedResponseData, required)
- `error` (HybridError, required)

### HybridBusinessDedupeLenderResult

- `lenderID` (string, required)
- `status` (enum, required) — PENDING: awaiting a result; CLEAR: passes the check; NOT_CLEAR: does not pass; SKIPPED: check not required; ERROR: check failed technically, not a borrower rejection.
  - Allowed values: `CLEAR`, `NOT_CLEAR`, `SKIPPED`, `ERROR`, `PENDING`
- `decisionReference` (string, required, nullable) — Opaque reference for the lender decision, when available.
- `decidedAt` (datetime, required, nullable)
- `expiresAt` (datetime, required, nullable)
- `reasonCode` (string, required, nullable) — Safe reason code when available. Null if the lender did not supply one.

### HybridOfferPollingRateLimitedResponseData

- `polling` (HybridPolling, required)

### HybridPolling

- `shouldPoll` (boolean, required)
- `lastPoll` (datetime, required)
- `nextPoll` (datetime, required)

## Examples

### Anonymised (Hashed) Dedupe

**Request**

```json
{
  "journeyType": "BUSINESS_LOAN",
  "identifiers": {
    "pan": "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
    "mobileNumber": "b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2"
  }
}
```

**Response**

```json
{
  "request_id": "30000000-0000-4000-8000-000000000001",
  "correlation_id": "40000000-0000-4000-8000-000000000001",
  "timestamp": "2026-10-28T09:00:00Z",
  "data": {
    "journeyID": "10000000-0000-4000-8000-000000000001",
    "stage": "DEDUPE",
    "status": "PENDING",
    "lenders": [
      {
        "lenderID": "example-lender-a",
        "status": "PENDING",
        "decisionReference": null,
        "decidedAt": null,
        "expiresAt": null,
        "reasonCode": null
      },
      {
        "lenderID": "example-lender-b",
        "status": "PENDING",
        "decisionReference": null,
        "decidedAt": null,
        "expiresAt": null,
        "reasonCode": null
      }
    ]
  },
  "error": null
}
```

**SDK Code**

```python Anonymised (Hashed) Dedupe
import requests

url = "https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe"

payload = {
    "journeyType": "BUSINESS_LOAN",
    "identifiers": {
        "pan": "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
        "mobileNumber": "b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2"
    }
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Anonymised (Hashed) Dedupe
const url = 'https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"journeyType":"BUSINESS_LOAN","identifiers":{"pan":"a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1","mobileNumber":"b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2"}}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Anonymised (Hashed) Dedupe
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe"

	payload := strings.NewReader("{\n  \"journeyType\": \"BUSINESS_LOAN\",\n  \"identifiers\": {\n    \"pan\": \"a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1\",\n    \"mobileNumber\": \"b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2\"\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Anonymised (Hashed) Dedupe
require 'uri'
require 'net/http'

url = URI("https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"journeyType\": \"BUSINESS_LOAN\",\n  \"identifiers\": {\n    \"pan\": \"a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1\",\n    \"mobileNumber\": \"b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2\"\n  }\n}"

response = http.request(request)
puts response.read_body
```

```java Anonymised (Hashed) Dedupe
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"journeyType\": \"BUSINESS_LOAN\",\n  \"identifiers\": {\n    \"pan\": \"a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1\",\n    \"mobileNumber\": \"b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2\"\n  }\n}")
  .asString();
```

```php Anonymised (Hashed) Dedupe
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe', [
  'body' => '{
  "journeyType": "BUSINESS_LOAN",
  "identifiers": {
    "pan": "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
    "mobileNumber": "b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2"
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Anonymised (Hashed) Dedupe
using RestSharp;

var client = new RestClient("https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"journeyType\": \"BUSINESS_LOAN\",\n  \"identifiers\": {\n    \"pan\": \"a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1\",\n    \"mobileNumber\": \"b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Anonymised (Hashed) Dedupe
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "journeyType": "BUSINESS_LOAN",
  "identifiers": [
    "pan": "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
    "mobileNumber": "b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2"
  ]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Un-Anonymised (Un-Hashed) Dedupe

**Request**

```json
{
  "journeyType": "BUSINESS_LOAN",
  "identifiers": {
    "pan": "ABCDE1234F",
    "mobileNumber": "9999999999"
  }
}
```

**Response**

```json
{
  "request_id": "30000000-0000-4000-8000-000000000001",
  "correlation_id": "40000000-0000-4000-8000-000000000001",
  "timestamp": "2026-10-28T09:00:00Z",
  "data": {
    "journeyID": "10000000-0000-4000-8000-000000000001",
    "stage": "DEDUPE",
    "status": "PENDING",
    "lenders": [
      {
        "lenderID": "example-lender-a",
        "status": "PENDING",
        "decisionReference": null,
        "decidedAt": null,
        "expiresAt": null,
        "reasonCode": null
      },
      {
        "lenderID": "example-lender-b",
        "status": "PENDING",
        "decisionReference": null,
        "decidedAt": null,
        "expiresAt": null,
        "reasonCode": null
      }
    ]
  },
  "error": null
}
```

**SDK Code**

```python Un-Anonymised (Un-Hashed) Dedupe
import requests

url = "https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe"

payload = {
    "journeyType": "BUSINESS_LOAN",
    "identifiers": {
        "pan": "ABCDE1234F",
        "mobileNumber": "9999999999"
    }
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Un-Anonymised (Un-Hashed) Dedupe
const url = 'https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"journeyType":"BUSINESS_LOAN","identifiers":{"pan":"ABCDE1234F","mobileNumber":"9999999999"}}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Un-Anonymised (Un-Hashed) Dedupe
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe"

	payload := strings.NewReader("{\n  \"journeyType\": \"BUSINESS_LOAN\",\n  \"identifiers\": {\n    \"pan\": \"ABCDE1234F\",\n    \"mobileNumber\": \"9999999999\"\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Un-Anonymised (Un-Hashed) Dedupe
require 'uri'
require 'net/http'

url = URI("https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"journeyType\": \"BUSINESS_LOAN\",\n  \"identifiers\": {\n    \"pan\": \"ABCDE1234F\",\n    \"mobileNumber\": \"9999999999\"\n  }\n}"

response = http.request(request)
puts response.read_body
```

```java Un-Anonymised (Un-Hashed) Dedupe
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"journeyType\": \"BUSINESS_LOAN\",\n  \"identifiers\": {\n    \"pan\": \"ABCDE1234F\",\n    \"mobileNumber\": \"9999999999\"\n  }\n}")
  .asString();
```

```php Un-Anonymised (Un-Hashed) Dedupe
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe', [
  'body' => '{
  "journeyType": "BUSINESS_LOAN",
  "identifiers": {
    "pan": "ABCDE1234F",
    "mobileNumber": "9999999999"
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Un-Anonymised (Un-Hashed) Dedupe
using RestSharp;

var client = new RestClient("https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"journeyType\": \"BUSINESS_LOAN\",\n  \"identifiers\": {\n    \"pan\": \"ABCDE1234F\",\n    \"mobileNumber\": \"9999999999\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Un-Anonymised (Un-Hashed) Dedupe
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "journeyType": "BUSINESS_LOAN",
  "identifiers": [
    "pan": "ABCDE1234F",
    "mobileNumber": "9999999999"
  ]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://credit.aarthiklabs.com/api/v1/hybrid/business-loan/borrowers/borrower-example-001/journey/dedupe")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```