API Sathi docs
← All products

Lead Enrichment

kyc

One call that turns a lead into a profile. Send a mobile number — and a PAN if you have one — and we run the relevant lookups across the catalogue and return a single merged result: employment, GST, MSME, directorships and company. THE SECOND HOP IS THE POINT. Identifiers discovered in the first pass are followed automatically: a DIN found from the PAN fetches director details, a CIN fetches company master data. You never round-trip to chase them yourself. PRICING IS NOT FIXED — READ THIS BEFORE BUDGETING. You pay the normal price of each sub-lookup that SUCCEEDED, and nothing for the ones that failed or were skipped. There is no separate orchestration fee. The price shown on this page is the basic-tier FLOOR; a full-tier call on a rich lead costs considerably more. Every response itemises each lookup and what it cost in `lookups[]`, and `totalSalePaise` is exactly what you were billed — so every invoice line traces back to a lookup. WHAT COUNTS AS BILLABLE: a lookup that returns a definitive "no record" IS billed — the source did the work, and `verified: false` is still information. A lookup that FAILED (upstream error) or was SKIPPED (you did not supply the input, or that source is unavailable) costs nothing. TIMING: basic returns in 1-3s. Full includes the MSME lookup, which is currently slow (24-27s), so set your client timeout to at least 45 seconds for `tier: "full"`.

POST /gw/v1/lead-enrich-v1/SLA p95: 40000 ms

Authentication

Pass your key in the X-API-Key header. Use a test_ key against the sandbox and a live_ key in production. Send an optional Idempotency-Key header to safely retry — the same key returns the same response for 24h.

X-API-Key: live_xxxxxxxxxxxx

Request

Endpoint: POST https://apisathi.in/gw/v1/lead-enrich-v1/

The trailing slash is required. /v1/lead-enrich-v1/ works; /v1/lead-enrich-v1 returns 404 Not Found. This applies to every product.

FieldTypeRequiredConstraints
mobilestringrequiredBorrower mobile number. Formatting is stripped; the last 10 digits are used.
panstringoptionalOptional but high value. Unlocks PAN verification, GSTIN-by-PAN, directorships and company lookups. Without it only the mobile-based lookups run.
tierstringoptionalbasic = employment + GST by mobile. standard = adds PAN verification, GSTIN by PAN, directorships and director detail. full = adds MSME/Udyam, company by PAN, company and GST detail. Defaults to basic. Tiers are cumulative.

Code snippets

curl -X POST https://apisathi.in/gw/v1/lead-enrich-v1/ \
  -H "X-API-Key: $API_SATHI_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"mobile":"9876543210","pan":"ABCDE1234F","tier":"standard"}'

Response

FieldTypeRequiredConstraints
tierstringoptionalThe tier that was actually run.
profileobjectoptionalMerged enrichment. Keys appear only when that lookup succeeded: employment, gst_by_mobile, pan, gstins, directorships, msme, company_by_pan, and the second-hop director_detail, company_detail, gst_detail.
lookupsarrayoptionalOne entry per attempted lookup: { product, status, salePaise, costPaise, reason }. status is ok | no_data | failed | skipped.
totalSalePaisenumberoptionalWhat you were billed — the sum of successful lookups only.

Sample response

{
  "tier": "standard",
  "profile": {
    "pan": {
      "verified": true,
      "name": "RAHUL VERMA"
    },
    "employment": {
      "uan": "XXXXXXXX1234",
      "employer": "ACME PRIVATE LIMITED"
    },
    "directorships": {
      "din": "09999999"
    },
    "director_detail": {
      "name": "RAHUL VERMA",
      "companies": 2
    }
  },
  "lookups": [
    {
      "product": "uan-basic-v3",
      "status": "ok",
      "salePaise": 450,
      "costPaise": 150
    },
    {
      "product": "contact-to-gst-v1",
      "status": "no_data",
      "salePaise": 210,
      "costPaise": 70
    },
    {
      "product": "pan-verification-v1",
      "status": "ok",
      "salePaise": 240,
      "costPaise": 80
    },
    {
      "product": "gstin-by-pan-v1",
      "status": "failed",
      "salePaise": 0,
      "costPaise": 0,
      "reason": "VENDOR_ERROR"
    },
    {
      "product": "pan-to-din-v1",
      "status": "ok",
      "salePaise": 135,
      "costPaise": 45
    },
    {
      "product": "din-basic-v1",
      "status": "ok",
      "salePaise": 150,
      "costPaise": 50
    }
  ],
  "totalSalePaise": 1185
}

Reading a 400

A schema rejection returns INVALID_REQUEST with a details array naming the exact field. Read it before guessing — it gives you the JSON path and what was wrong with it.

{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Request body failed schema validation",
    "details": [
      { "path": "/callback_url",
        "message": "unexpected property 'callback_url' — this endpoint does not accept unknown fields" }
    ]
  }
}

Most endpoints reject unknown top-level fields outright, so an extra key you added for your own bookkeeping will fail the call. Enum errors list the accepted values, and a missing required field is named with its full path.

Error codes

CodeHTTPWhen
INVALID_INPUT422The request was rejected as invalid — either it failed OUR schema validation (malformed input; not charged), or the upstream source rejected the value you sent. NOTE: an identifier that is well-formed but simply has NO RECORD is no longer an error — it returns 200 with `verified: false` and is charged (see the result-code table below). FIX the input before retrying; retrying the same value will fail again.
INVALID_API_KEY401Missing, malformed, or revoked X-API-Key.
OUT_OF_SCOPE403API key is not scoped for this product.
INSUFFICIENT_BALANCE402Wallet balance is below the per-call sale price. Recharge and retry.
RATE_LIMITED429Per-key RPS or RPM limit exceeded. Back off and retry after the Retry-After header.
PRODUCT_DEPRECATED410This API has been retired and is no longer available. Stop calling it — it will not return. Check the catalog for the current equivalent.
ROUTER_NO_VENDOR503No healthy vendor is currently available for this product. Transient — safe to retry after a short backoff. Not charged.
VENDOR_AUTH_FAILED502Upstream vendor rejected our credentials (our config issue). Not charged.
VENDOR_ERROR502A genuine transient upstream error (the source was briefly unavailable). Safe to RETRY after a short backoff. Not charged. NOTE: this is NOT for bad input — invalid values return 422 INVALID_INPUT, not 502.
TIMEOUT504Upstream vendor did not respond within the SLA window. Safe to retry after a short backoff. Not charged.

OpenAPI 3.1

Generated from this product's request/response JSON Schemas.

{
  "openapi": "3.1.0",
  "info": {
    "title": "API Sathi — Lead Enrichment",
    "version": "1.0.0",
    "description": "One call that turns a lead into a profile. Send a mobile number — and a PAN if you have one — and we run the relevant lookups across the catalogue and return a single merged result: employment, GST, MSME, directorships and company.\n\nTHE SECOND HOP IS THE POINT. Identifiers discovered in the first pass are followed automatically: a DIN found from the PAN fetches director details, a CIN fetches company master data. You never round-trip to chase them yourself.\n\nPRICING IS NOT FIXED — READ THIS BEFORE BUDGETING. You pay the normal price of each sub-lookup that SUCCEEDED, and nothing for the ones that failed or were skipped. There is no separate orchestration fee. The price shown on this page is the basic-tier FLOOR; a full-tier call on a rich lead costs considerably more. Every response itemises each lookup and what it cost in `lookups[]`, and `totalSalePaise` is exactly what you were billed — so every invoice line traces back to a lookup.\n\nWHAT COUNTS AS BILLABLE: a lookup that returns a definitive \"no record\" IS billed — the source did the work, and `verified: false` is still information. A lookup that FAILED (upstream error) or was SKIPPED (you did not supply the input, or that source is unavailable) costs nothing.\n\nTIMING: basic returns in 1-3s. Full includes the MSME lookup, which is currently slow (24-27s), so set your client timeout to at least 45 seconds for `tier: \"full\"`."
  },
  "servers": [
    {
      "url": "https://apisathi.in/gw/v1"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Your live or test key, e.g. `live_xxxxxxxxxxxx`."
      }
    }
  },
  "paths": {
    "/lead-enrich-v1": {
      "post": {
        "operationId": "leadEnrichV1",
        "tags": [
          "kyc"
        ],
        "summary": "Lead Enrichment",
        "description": "One call that turns a lead into a profile. Send a mobile number — and a PAN if you have one — and we run the relevant lookups across the catalogue and return a single merged result: employment, GST, MSME, directorships and company.\n\nTHE SECOND HOP IS THE POINT. Identifiers discovered in the first pass are followed automatically: a DIN found from the PAN fetches director details, a CIN fetches company master data. You never round-trip to chase them yourself.\n\nPRICING IS NOT FIXED — READ THIS BEFORE BUDGETING. You pay the normal price of each sub-lookup that SUCCEEDED, and nothing for the ones that failed or were skipped. There is no separate orchestration fee. The price shown on this page is the basic-tier FLOOR; a full-tier call on a rich lead costs considerably more. Every response itemises each lookup and what it cost in `lookups[]`, and `totalSalePaise` is exactly what you were billed — so every invoice line traces back to a lookup.\n\nWHAT COUNTS AS BILLABLE: a lookup that returns a definitive \"no record\" IS billed — the source did the work, and `verified: false` is still information. A lookup that FAILED (upstream error) or was SKIPPED (you did not supply the input, or that source is unavailable) costs nothing.\n\nTIMING: basic returns in 1-3s. Full includes the MSME lookup, which is currently slow (24-27s), so set your client timeout to at least 45 seconds for `tier: \"full\"`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional. Same key returns the same response for 24h."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "mobile"
                ],
                "properties": {
                  "mobile": {
                    "type": "string",
                    "description": "Borrower mobile number. Formatting is stripped; the last 10 digits are used."
                  },
                  "pan": {
                    "type": "string",
                    "description": "Optional but high value. Unlocks PAN verification, GSTIN-by-PAN, directorships and company lookups. Without it only the mobile-based lookups run."
                  },
                  "tier": {
                    "type": "string",
                    "enum": [
                      "basic",
                      "standard",
                      "full"
                    ],
                    "description": "basic = employment + GST by mobile. standard = adds PAN verification, GSTIN by PAN, directorships and director detail. full = adds MSME/Udyam, company by PAN, company and GST detail. Defaults to basic. Tiers are cumulative."
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "mobile": "9876543210",
                "pan": "ABCDE1234F",
                "tier": "standard"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful, normalized response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tier": {
                      "type": "string",
                      "description": "The tier that was actually run."
                    },
                    "profile": {
                      "type": "object",
                      "description": "Merged enrichment. Keys appear only when that lookup succeeded: employment, gst_by_mobile, pan, gstins, directorships, msme, company_by_pan, and the second-hop director_detail, company_detail, gst_detail."
                    },
                    "lookups": {
                      "type": "array",
                      "description": "One entry per attempted lookup: { product, status, salePaise, costPaise, reason }. status is ok | no_data | failed | skipped."
                    },
                    "totalSalePaise": {
                      "type": "number",
                      "description": "What you were billed — the sum of successful lookups only."
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "tier": "standard",
                  "profile": {
                    "pan": {
                      "verified": true,
                      "name": "RAHUL VERMA"
                    },
                    "employment": {
                      "uan": "XXXXXXXX1234",
                      "employer": "ACME PRIVATE LIMITED"
                    },
                    "directorships": {
                      "din": "09999999"
                    },
                    "director_detail": {
                      "name": "RAHUL VERMA",
                      "companies": 2
                    }
                  },
                  "lookups": [
                    {
                      "product": "uan-basic-v3",
                      "status": "ok",
                      "salePaise": 450,
                      "costPaise": 150
                    },
                    {
                      "product": "contact-to-gst-v1",
                      "status": "no_data",
                      "salePaise": 210,
                      "costPaise": 70
                    },
                    {
                      "product": "pan-verification-v1",
                      "status": "ok",
                      "salePaise": 240,
                      "costPaise": 80
                    },
                    {
                      "product": "gstin-by-pan-v1",
                      "status": "failed",
                      "salePaise": 0,
                      "costPaise": 0,
                      "reason": "VENDOR_ERROR"
                    },
                    {
                      "product": "pan-to-din-v1",
                      "status": "ok",
                      "salePaise": 135,
                      "costPaise": 45
                    },
                    {
                      "product": "din-basic-v1",
                      "status": "ok",
                      "salePaise": 150,
                      "costPaise": 50
                    }
                  ],
                  "totalSalePaise": 1185
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked X-API-Key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "call_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Wallet balance is below the per-call sale price. Recharge and retry.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "call_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "API key is not scoped for this product.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "call_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "410": {
            "description": "This API has been retired and is no longer available. Stop calling it — it will not return. Check the catalog for the current equivalent.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "call_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "The request was rejected as invalid — either it failed OUR schema validation (malformed input; not charged), or the upstream source rejected the value you sent. NOTE: an identifier that is well-formed but simply has NO RECORD is no longer an error — it returns 200 with `verified: false` and is charged (see the result-code table below). FIX the input before retrying; retrying the same value will fail again.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "call_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Per-key RPS or RPM limit exceeded. Back off and retry after the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "call_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Upstream vendor rejected our credentials (our config issue). Not charged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "call_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "No healthy vendor is currently available for this product. Transient — safe to retry after a short backoff. Not charged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "call_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "504": {
            "description": "Upstream vendor did not respond within the SLA window. Safe to retry after a short backoff. Not charged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "call_id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}