When a business signs up to buy, sell, borrow or transact on your platform, you are not onboarding a person. You are onboarding a legal entity that exists in several registers at once: the income-tax register under a PAN, the GST register under one or more GSTINs, the company register under a CIN if it is a company, and possibly the MSME register under a Udyam number. Know Your Business, or KYB, is the discipline of checking that these records exist, are active, agree with each other and agree with what the applicant told you. This page is for B2B platforms in India: SaaS products selling to companies, B2B marketplaces, trade-credit and invoice-finance providers, distributors, procurement tools and business banking apps.
It sits next to the business verification guide, which explains what each identifier proves and how to call each endpoint. This page is about running KYB as a program: how to decide which checks an entity needs, how to cross-check records against each other, how to turn the results into limits and terms, and how to keep watching after onboarding. The checks show what registries say; they do not tell you whether a business is creditworthy or honest, and they are not legal advice.
Key takeaways
- KYB is a consistency exercise. The value is not in any single registry hit but in whether PAN, GSTIN, CIN and Udyam records agree with each other and with the applicant's declaration.
- Anchor everything on the PAN. A GSTIN embeds the PAN of the taxpayer, so one of the cheapest and strongest checks is free: compare the PAN inside the GSTIN with the PAN you hold.
- Choose checks by entity type. A company, a proprietorship, a partnership, an LLP and a trust bring different identifiers, and a single flow for all of them either over-asks or under-checks.
- The CIN response lists directors with DIN, name and designation. That helps you identify the people behind a company. It does not establish beneficial ownership, which needs documents and judgement outside a registry lookup.
- Turn results into tiers: what credit, limits and terms an entity gets should follow from how much of the picture you have verified.
- Monitoring matters as much as onboarding. Registrations get cancelled and companies get struck off. A schedule and event triggers catch drift.
valid: falseandfound: falseare completed, billable answers. Retry only 429 and 502.- A company flow with a signatory PAN and a bank account costs a few tens of rupees per business; the arithmetic for three volumes is below.
KYB in plain terms, and how it differs from KYC
KYC is about a person. KYB is about an entity and the people connected to it. The two overlap, because a business is operated by people, and a KYB program normally includes KYC-style checks on the signatory or the proprietor. But the questions are different.
For a person you ask whether the identity document is genuine and whether it matches the name. For a business you ask whether the entity exists in the registers it claims to be in, whether those registrations are active, whether the name and address agree across them, who stands behind the entity, and whether the person applying is entitled to act for it. A business can be perfectly real and the applicant still a stranger to it, which is why signatory checks and authority documents matter.
The regulatory language around business customers, such as customer due diligence and beneficial ownership for regulated entities, is the territory of your regulator's rules and your compliance function. If you are a regulated entity, your policy decides what is enough. This page covers what an API can contribute and how to use it carefully.
What a B2B platform needs to know about a business
Write down the questions before you pick endpoints. Most platforms care about six.
- Does the entity exist, and as what? A private company, a proprietorship, a partnership, an LLP, a trust.
- Is it active? Registrations that were valid at signup may not be valid now.
- Does the name agree? Legal name, trade name and the name on your form should be explainable.
- Where is it? Registered address and state, compared with where the applicant says it operates.
- Who is behind it? Directors for a company, the proprietor for a sole proprietorship, partners for a firm.
- Is the applicant authorised? A person signing up for a company account should be someone the company recognises.
Questions 1 to 4 are registry questions an API can answer. Question 5 is partly answerable, for companies, through the directors list. Question 6 is a document and process question.
Entity types and the identifiers each brings
| Entity type | Identifiers you can expect | Endpoints | Notes |
|---|---|---|---|
| Private or public limited company | PAN, CIN, GSTIN, sometimes Udyam | verify/pan, verify/cin, verify/gstin, verify/udyam | CIN call returns status and directors |
| One-person company | As above | As above | Treat like a company; the director is also the owner |
| LLP | PAN, GSTIN, sometimes Udyam | verify/pan, verify/gstin, verify/udyam | There is no CIN-style endpoint for an LLP on this platform; rely on PAN, GSTIN and documents |
| Partnership firm | PAN, GSTIN if registered, sometimes Udyam | verify/pan, verify/gstin, verify/udyam | Partners are individuals; check at least the signatory |
| Sole proprietorship | Proprietor's PAN, GSTIN if registered, sometimes Udyam | verify/pan, verify/gstin, verify/udyam | Legal name on the GSTIN is the proprietor's; the trade name is the shop |
| Trust, society, government body | PAN, sometimes GSTIN | verify/pan, verify/gstin where present | Route to a manual path; registries differ |
| Foreign entity | Not applicable | None of these | Separate process outside this API |
A useful structure for the PAN is that its fourth character indicates the type of holder, such as a company, a firm or an individual, so the PAN type from verify/pan should agree with the entity type the applicant selected. A company with an individual's PAN, or a proprietorship with a company PAN, is a consistency failure worth a question.
The PAN anchor and the consistency graph
Think of the checks as a small graph with the PAN at the centre. Each registry record is a node connected by edges that should hold. The table lists the edges and what each tells you.
| Edge | How you check it | Cost | What a failure suggests |
|---|---|---|---|
| PAN inside the GSTIN equals the PAN you hold | Compare characters three to twelve of the GSTIN, locally | Free | Typo, borrowed GSTIN or a different taxpayer |
| GSTIN state code agrees with the declared state | Compare the first two digits with the address state | Free | Multi-state business, or a mismatch to explain |
| PAN type agrees with entity type | type from verify/pan against the declared type | One PAN call | Wrong entity type selected or a borrowed PAN |
| Name on PAN agrees with the declared legal name | nameMatchScore from verify/pan | One PAN call | Typos, trade name entered as legal name |
legalName on the GSTIN agrees with the PAN name | Your own tolerant comparison | One GSTIN call | Different taxpayer or renamed entity |
| CIN year agrees with the incorporation date | Compare the year inside the CIN with incorporationDate | One CIN call | Typo or borrowed CIN |
| GSTIN is among the GSTINs linked to the PAN | verify/pan-to-gstin | One call | Borrowed GSTIN or a registration under a different PAN |
| Directors listed include the signatory | Compare the signatory's name with directors | Part of the CIN call | Applicant not connected to the company |
The first two are free, the middle ones come with calls you were making anyway, and only the PAN-to-GSTIN edge needs a call that is purely for consistency. Run the free edges first, then the calls, and stop early on a hard failure to avoid spending on an entity that will not pass.
The workflow, step by step
- Collect the declaration. Legal name, entity type, PAN, GSTIN and CIN where applicable, Udyam if claimed, registered address and state, signatory name and PAN, and the bank account for payments or credit. Decision: nothing paid yet; the business is created in a "pending KYB" state.
- Run the free edges. Pattern checks, PAN-inside-GSTIN, GSTIN state versus address. Decision: send the form back with a precise message, or continue.
- Verify the entity PAN.
POST /v1/verify/panwith the PAN and the declared legal name. Readvalid,type,registeredName,nameMatchScore. Decision: invalid stops; a type that contradicts the declaration goes to review; a weak score goes to review. - Verify the registration.
POST /v1/verify/gstinfor GST-registered businesses,POST /v1/verify/cinfor companies. Read the status fields (registrationStatus,companyStatus,cinStatus) and the names. Decision: inactive stops or goes to documents per policy; unexplained name differences go to review. - Cross-check linked registrations.
POST /v1/verify/pan-to-gstinwhere you need to confirm that the GSTIN belongs to the PAN, or to see other registrations. Decision: a declared GSTIN that is not linked goes to review. - Verify Udyam where claimed.
POST /v1/verify/udyam. Decision: record the type and status if found; otherwise do not record the MSME claim. - Verify the signatory.
POST /v1/verify/panon the signatory's PAN with their name; for a company, compare the name with the directors list. Decision: signatory not connected to the entity goes to review for an authority document. - Verify the bank account.
POST /v1/verify/bank-accountwith the business's account and legal name, if you will pay or collect. Decision: account in the entity's name proceeds; otherwise review. - Score and tier. Compute the verified-signals picture and assign a tier. Decision: tier sets limits and terms.
- Record and schedule monitoring. Store evidence and schedule status re-checks by tier.
Sample request and response: verifying a company by CIN
The CIN call returns the facts you need to anchor a company and the directors to compare with the applicant:
curl -X POST "https://api-b2b.stampmitra.in/v1/verify/cin" \
-H "Authorization: Bearer $STAMPMITRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"cin":"U74999DL2015PTC284009"}'{
"referenceId": "SMV-20260927-6R38Y3",
"valid": true,
"companyName": "JANE DOE ENTERPRISES PRIVATE LIMITED",
"incorporationDate": "2015-03-12",
"cinStatus": "ACTIVE",
"companyStatus": "Active",
"directors": [
{ "din": "01234567", "name": "RAHUL KUMAR", "designation": "Director" }
],
"email": "[email protected]",
"registrationNumber": 284009,
"incorporationCountry": "India"
}| Field | Meaning | Use in KYB |
|---|---|---|
valid | The CIN resolved | false stops the company flow after one re-entry |
companyName | Registered name | Compare with the declared legal name and the PAN name |
incorporationDate | Date of incorporation | The year should match the year inside the CIN; use age as a risk signal if your policy does |
cinStatus, companyStatus | Status of the CIN and of the company | Anything other than active needs a decision |
directors | Directors with DIN, name and designation | Compare with the signatory; show reviewers the names |
email | Contact email on record | Do not use as verification of the applicant's identity; it is a registry field |
registrationNumber | Company registration number, a number | Should equal the last six digits of the CIN you sent, compared as numbers |
referenceId | StampMitra transaction id | Store with the KYB record |
A CIN itself carries structure you can read locally: a letter for listed or unlisted status, a five-digit industry code, a two-letter state code, the year of incorporation, a three-letter code for the type of company (private, public, one-person and so on) and a six-digit registration number. That makes the year-of-incorporation edge a free consistency check once the response arrives.
A consistency function
The Node function below evaluates the edges and returns a list of findings with a severity. The thresholds and the names comparison are starting points to tune.
function gstinPan(gstin) {
return gstin && gstin.length === 15 ? gstin.slice(2, 12) : null;
}
export function evaluateKyb({ declared, pan, gstin, cin }) {
const findings = [];
const add = (severity, code, detail) => findings.push({ severity, code, detail });
if (declared.gstin && gstinPan(declared.gstin) !== declared.pan) {
add("hard", "PAN_NOT_IN_GSTIN", "PAN inside the GSTIN differs from the declared PAN");
}
if (pan && !pan.valid) add("hard", "PAN_INVALID", pan.message);
if (pan?.valid && declared.entityType === "company" && !/company/i.test(String(pan.type))) {
add("review", "PAN_TYPE_MISMATCH", `PAN type ${pan.type} for a company`);
}
if (pan?.valid && Number(pan.nameMatchScore) < 70) {
add("review", "PAN_NAME_WEAK", `score ${pan.nameMatchScore}`);
}
if (gstin && gstin.valid === false) add("hard", "GSTIN_INVALID", "GSTIN not found");
if (gstin?.valid && String(gstin.registrationStatus).toLowerCase() !== "active") {
add("hard", "GSTIN_INACTIVE", gstin.registrationStatus);
}
if (cin && cin.valid === false) add("hard", "CIN_INVALID", "CIN not found");
if (cin?.valid) {
if (String(cin.companyStatus).toLowerCase() !== "active") add("hard", "COMPANY_INACTIVE", cin.companyStatus);
const yearInCin = declared.cin?.slice(8, 12);
if (yearInCin && cin.incorporationDate?.slice(0, 4) !== yearInCin) {
add("review", "CIN_YEAR_MISMATCH", `${yearInCin} vs ${cin.incorporationDate}`);
}
const signatory = declared.signatoryName?.toLowerCase().split(/\s+/) ?? [];
const hit = (cin.directors ?? []).some((d) => signatory.every((w) => d.name.toLowerCase().includes(w)));
if (!hit) add("review", "SIGNATORY_NOT_A_DIRECTOR", "ask for an authority document");
}
return findings;
}Decision table: valid, mismatch, inactive, not found
| Outcome | PAN | GSTIN | CIN | Udyam |
|---|---|---|---|---|
| Valid and consistent | Record; continue | Record state and status | Record directors and status | Record type and status |
| Valid, name or type mismatch | Review with the declared type and names | Review; legal and trade names often differ | Review; compare with the PAN name | Review the enterprise name |
| Inactive, cancelled or lapsed | Stop; the status explains why | Stop or move to documents per policy | Stop; do not onboard a company that is not active | Do not record the MSME claim |
Not found or valid: false | One re-entry, then stop | One re-entry, then documents | One re-entry, then documents | Treat as non-MSME until proven |
| Call failed | Pending; retry | Pending; retry | Pending; retry | Pending; retry |
Name and address differences across registers
The most common reason a genuine business fails an automated KYB check is not fraud but formatting. The same company appears as "Jane Doe Enterprises Private Limited" on the company register, "JANE DOE ENTERPRISES PVT LTD" on a tax record and "Jane Doe Enterprises" on a signboard. A business may have been renamed, with one register updated before another. A proprietorship's GSTIN legal name is the owner's personal name while the shop trades under a brand.
Build the comparison in layers. First normalise: upper-case, remove punctuation, expand or strip common suffixes such as private, pvt, limited, ltd and LLP, and collapse whitespace. Second compare the normalised token sets and compute an overlap ratio rather than testing equality. Third, make the result a finding with a severity: a high overlap passes quietly, a middling overlap becomes a review item with both names shown, and a low overlap becomes a hard finding only when combined with another inconsistency. A single weak name signal should rarely stop an otherwise consistent entity.
Addresses are harder. The registered address on a company record, the principal place of business on a GSTIN and the address your applicant types will often differ legitimately, because a business may operate from a site other than its registered office and may hold registrations in several states. Use the state, not the street, for automatic checks, and treat a state difference as a question rather than a failure: ask whether the business has operations in that state and whether the GSTIN you hold is the one for it. Keep the full address comparison for the human reviewer.
For renamed entities, the signal is usually in the dates. A recent change on one register and not the other, together with agreement on PAN and CIN, points towards a rename; ask the applicant for the document that shows it, record the reason and update the stored legal name from the verified record. Do not overwrite the applicant's declared name silently, because the declaration is part of your evidence.
Record every name and address decision with its reason. Over time those reasons become your rule list: patterns that reviewers always clear become automatic passes, and patterns that reviewers often decline become hard stops. Review the list every quarter, because a rule that was right when you had fifty customers can be wrong at five thousand.
Directors, owners and what an API cannot tell you
The CIN response lists directors. That is useful: it gives your reviewers real names to recognise and a list to compare the signatory against. It is not a statement of who owns the company. Ownership, including who ultimately controls it through shareholdings or other means, is established from documents such as shareholding statements and from your own judgement, and the rules on beneficial ownership for regulated entities come from your regulator and your policy, not from this endpoint.
Two practical consequences. First, if your policy requires you to identify owners above a threshold, plan a document step and a human reviewer; do not pretend the directors list answers it. Second, if a director or signatory needs to be identified as an individual, run the individual checks on them: PAN with name, and where relevant a bank account. The KYC for NBFC loan origination page describes those personal checks.
Turning the picture into tiers
Not every business needs the same scrutiny, and the tier should follow what you have verified and what you are exposing. A simple structure scores the verified signals and then maps score and exposure to a tier. The table is an example, to adapt with your risk team.
| Signal verified | Suggested weight | Notes |
|---|---|---|
| PAN valid, type and name agree | High | The anchor |
| GSTIN active, PAN inside it agrees | High | Strong for tax-invoice businesses |
| CIN active, name agrees | High | For companies |
| Signatory connected to the entity | Medium | Directors list or authority document |
| Bank account in the entity's name | Medium | Needed for payments and credit |
| Udyam found and active | Low | Self-declared classification; use for MSME terms only |
| Entity age from incorporation date | Low | A risk signal, not proof of quality |
| Tier | What you have verified | Typical exposure |
|---|---|---|
| A | All high signals, signatory and bank | Higher limits, credit terms |
| B | High signals, bank, signatory pending | Standard limits, prepayment or short terms |
| C | PAN only, or partial registrations | Low limits, prepayment only |
| D | Failed or inconsistent | Review before any exposure |
Write the rule down, give it a version number and record the version with each decision. When risk appetite changes, change the rule, not the people applying it.
Ongoing monitoring: status drift
A business that was active at onboarding can become inactive later: a GST registration is cancelled, a company is struck off, a bank account is closed, a director resigns. Onboarding KYB without monitoring is a snapshot that ages.
Monitor by tier. Tier A entities with large exposure get a short re-check interval you choose for registration and company status, and a re-check on any change of bank account or signatory. Tier B and C entities get a longer interval or a trigger-only policy. Add event triggers on top of the calendar: a returned payment, a delayed payment, a dispute, a request to change account or signatory, a notice about the entity from a buyer or seller, or a sudden change in activity.
import os
import requests
BASE = "https://api-b2b.stampmitra.in"
HEADERS = {
"Authorization": f"Bearer {os.environ['STAMPMITRA_API_KEY']}",
"Content-Type": "application/json",
}
def recheck_status(entity: dict) -> list[str]:
changes = []
if entity.get("gstin"):
r = requests.post(f"{BASE}/v1/verify/gstin", headers=HEADERS, json={"gstin": entity["gstin"]}, timeout=20)
if r.ok:
status = str(r.json().get("registrationStatus", "")).lower()
if status != "active":
changes.append(f"GSTIN status now {status or 'unknown'}")
if entity.get("cin"):
r = requests.post(f"{BASE}/v1/verify/cin", headers=HEADERS, json={"cin": entity["cin"]}, timeout=20)
if r.ok:
status = str(r.json().get("companyStatus", "")).lower()
if status != "active":
changes.append(f"company status now {status or 'unknown'}")
return changesWhen a recheck shows a change, open an exception, notify the account owner, and decide with the credit or risk team what happens to open exposure. The code decides nothing about the relationship; it only surfaces the change.
Entities without registrations
Some legitimate businesses have no GSTIN or CIN: small proprietorships below the registration threshold, informal traders, trusts, societies and foreign entities. A KYB flow that fails them all is a flow that excludes real customers. Define a lighter path for each: for proprietors, the proprietor's PAN with name and a bank account in their name; for trusts and societies, the PAN and documents reviewed by a person; for foreign entities, a separate process outside this API. Tier these entities by what you can verify, and set limits to match. The lighter the evidence, the lower the exposure, and prepayment remains an option.
The review packet and the operating model
When a case goes to a reviewer, give them one screen with everything. It should show the declaration next to each verified value, the findings from the consistency function with severity, the status fields, the directors list for companies, the tier the rules would assign, and the evidence ids. It should offer a short list of actions: approve at a tier, request documents, decline, or escalate. Every action takes a reason.
Run two queues. The KYB review queue holds findings that need judgement; it is staffed by analysts with a named senior reviewer, and a turnaround target that you set with the sales or onboarding team so that review does not become the reason deals stall. The monitoring queue holds status changes and trigger events and belongs to risk or credit operations. A third platform queue for failed calls and wallet alerts belongs to engineering.
Five scenarios from a KYB desk
These are hypothetical cases.
The clean company
A private company signs up with a PAN, a GSTIN and a CIN. The PAN-in-GSTIN edge passes, PAN type is company, the CIN is active, the director list includes the signatory, and the bank account is in the company's name. Tier A, same day.
The trade-name applicant
A distributor enters its brand as legal name. The PAN name score is middling; the GSTIN legalName is a long company name that contains the brand. A reviewer confirms with the applicant, records the reason and approves at tier B pending a bank check.
The borrowed GSTIN
An applicant enters a GSTIN whose embedded PAN differs from the PAN supplied. The free check fails before any paid call. The form returns with a precise message. If the applicant persists, the case goes to the risk queue.
The struck-off company
A company that has been a customer for a year is re-checked and the company status is no longer active. An exception opens, open orders are flagged, the account owner is told, and the credit team decides what to do about exposure and further sales.
The proprietor with no GST
A small proprietor has a PAN and a bank account but no GSTIN or CIN. The lighter path verifies the PAN with name and the account, assigns tier C, and allows prepaid orders only.
Six months later the proprietor registers for GST and asks for credit terms. The platform does not start again. It runs the registration checks on the new GSTIN, confirms that the PAN inside it equals the one already on file, records the new evidence next to the old, re-scores the entity and moves it to tier B. The earlier checks stay in the record, so the history of how the relationship was built remains visible to anyone who reviews it.
Review rules a B2B platform can copy
These are suggestions for your risk policy to adapt.
- Free checks first. No paid call before pattern, PAN-in-GSTIN and state checks pass.
- Stop on inactive. An inactive registration or company does not proceed without documents and a second approver.
- Entity type must agree. A mismatch between declared type and PAN type goes to review.
- Signatory must connect. For companies, a signatory outside the directors list requires an authority document.
- Tier drives terms. Credit and limits follow the tier, and the tier follows the evidence.
- Two approvers for tier upgrades without full evidence and for overrides of hard findings.
- Monitoring is not optional for tiers with credit exposure.
- Never decide on a single signal. Use signals to route to people and to tiers.
What to store and for how long
For each KYB record store the declaration, referenceId for each call, timestamps, the environment of the key, the response fields you used, the findings, the tier, the rule version, the reviewer and the reason for overrides. Keep identifiers masked in logs and in non-privileged views. Directors' names and DINs are personal data of individuals, and a sole proprietor's PAN is personal data too, so apply access controls accordingly.
Retention depends on contract and commercial law, tax and accounting rules, your regulator's requirements if you are regulated, and data-protection law for the individuals involved. We cannot give you periods. Take the question to your counsel, write the answer into a retention schedule, and automate it. StampMitra's own handling of data is described in its retention and deletion schedule and data processing addendum.
What it costs: three onboarding volumes
Pay-as-you-go prices are ₹5 per call for PAN, GSTIN, CIN, Udyam and the cross-lookups, and ₹4 for the bank-account check. Growth and Scale lower the standard rate and add a monthly plan fee; the bank rate is the same on every plan. All figures exclude GST at 18 percent.
The cost of one business depends on its type. A company with PAN, GSTIN, CIN, a signatory PAN and a bank account, and a sole proprietor with PAN, GSTIN and a bank account:
| Plan | Cost of one company before GST |
|---|---|
| Pay as you go | ₹24 |
| Growth | ₹20 |
| Scale | ₹18 |
| Plan | Cost of one sole proprietor before GST |
|---|---|
| Pay as you go | ₹14 |
| Growth | ₹12 |
| Scale | ₹11 |
For monthly models, assume an average business needs a PAN check, a GSTIN check, a CIN check for 40 percent of businesses, a Udyam check for 20 percent, a signatory PAN check and a bank check. That is 3.6 standard calls and one bank check per business. At 200 new businesses a month: 720 standard calls and 200 bank checks.
| Plan | Usage charges | Plan fee | Subtotal | GST at 18% | Total for the month |
|---|---|---|---|---|---|
| Pay as you go | ₹4,400 | ₹0 | ₹4,400 | ₹792 | ₹5,192 |
| Growth | ₹3,680 | ₹999 | ₹4,679 | ₹842.22 | ₹5,521.22 |
| Scale | ₹3,320 | ₹4,999 | ₹8,319 | ₹1,497.42 | ₹9,816.42 |
At 2,000 new businesses a month: 7,200 standard calls and 2,000 bank checks.
| Plan | Usage charges | Plan fee | Subtotal | GST at 18% | Total for the month |
|---|---|---|---|---|---|
| Pay as you go | ₹44,000 | ₹0 | ₹44,000 | ₹7,920 | ₹51,920 |
| Growth | ₹36,800 | ₹999 | ₹37,799 | ₹6,803.82 | ₹44,602.82 |
| Scale | ₹33,200 | ₹4,999 | ₹38,199 | ₹6,875.82 | ₹45,074.82 |
At 20,000 new businesses a month, as a very large platform might see: 72,000 standard calls and 20,000 bank checks.
| Plan | Usage charges | Plan fee | Subtotal | GST at 18% | Total for the month |
|---|---|---|---|---|---|
| Pay as you go | ₹4,40,000 | ₹0 | ₹4,40,000 | ₹79,200 | ₹5,19,200 |
| Growth | ₹3,68,000 | ₹999 | ₹3,68,999 | ₹66,419.82 | ₹4,35,418.82 |
| Scale | ₹3,32,000 | ₹4,999 | ₹3,36,999 | ₹60,659.82 | ₹3,97,658.82 |
Reading the tables: at 200 businesses a month pay as you go is cheapest because plan fees outweigh the lower rate; at 2,000 Growth is cheapest, with Scale close behind; at 20,000 Scale is cheapest, and the spend is above the level at which StampMitra suggests an enterprise arrangement, which is a conversation for the contact page. These totals leave out ongoing monitoring: re-checking a status costs one call per registration per check, so a monitoring schedule adds calls in proportion to your active base and your interval. Estimate it as active entities times calls per cycle times cycles per month, and add it to the model. The tables assume GST applies to the plan fee as well; confirm on an invoice. Usage is recorded after a successful response, so calls that fail with an error are not charged, although valid: false is a successful answer and is charged. Weigh the cost against the exposure you are protecting and the analyst time you save, using your own numbers.
Rollout: sandbox, pilot, production
Sandbox. Build the declaration form, consistency function, tiers and review packet against sandbox keys, where responses are sample data and the wallet is not debited. The sandbox responder gives documented outcomes for particular test values: a valid result for the PAN SNDBX0000A and an invalid one for SNDBX9999F; a valid, active result for the GSTIN 09SNDBX0000A1Z5 and a not-valid, cancelled result for 09SNDBX9999F1Z5; and a valid and a not-valid result for two test CINs listed in the dashboard. Other inputs give stable but arbitrary outcomes, so do not assert on them. Confirm current test values in the dashboard, since live validators check formats before sandbox logic runs. Test every row of the decision table, every finding code and the monitoring job.
Pilot. Request production access, which needs your organisation's KYC approval and the per-product application. Run new business sign-ups for one segment through the flow with your analysts checking by hand in parallel for a few weeks. Compare tiers, and write down every disagreement.
Production. Widen by segment. Turn on monitoring for the highest-exposure tier first. Alert on wallet balance, and keep the sandbox versus production keys guide for scopes and the IP allowlist.
Metrics worth watching
- Share of businesses reaching each tier, and time to tier.
- Findings by code, and the share cleared after review. A code that is rarely cleared is a good rule; one that is nearly always cleared may be too strict.
- Review queue size and age of the oldest item.
- Drift: status changes found by monitoring per thousand entities, and what happened next.
- Overrides and who approved them.
- Exposure by tier, and losses or disputes by tier, so that the tier rules can be tested against outcomes.
- Calls per business, including monitoring.
- Onboarding drop-off at the declaration step, which shows whether the form asks too much.
Mistakes that weaken a KYB program
- One flow for every entity type. It over-asks some and under-checks others.
- Treating a registry hit as proof of the applicant. The business can be real and the applicant a stranger.
- Reading the directors list as ownership. It is not.
- Skipping the free checks. They are the cheapest and strongest.
- Exact name equality. Legal, trade and form names differ legitimately.
- No monitoring. A snapshot ages.
- Letting one signal decide. Use tiers and review.
- Forgetting the signatory. The person applying must connect to the entity.
- Excluding entities that have no GSTIN or CIN. Build lighter, lower-exposure paths instead.
API reference at a glance
Company CIN
POST /v1/verify/cinRequest parameters
| Field | Type | Description |
|---|---|---|
Authorizationrequired | header | Bearer <api-key> (e.g. sk_test_... in sandbox, sk_live_... in production). The x-api-key header is also accepted. |
cinrequired | string | Corporate Identification Number (21 characters) or LLPIN, for example U74999DL2015PTC284009. |
POST /v1/verify/cin{
"referenceId": "SMV-20260927-6R38Y3",
"verificationId": "VRF-6C2N9V4HQ7ZE",
"valid": true,
"status": "VALID",
"cin": "U72900KA2015PTC082988",
"companyName": "COMPANY NAME",
"registrationNumber": 82987,
"incorporationDate": "2015-09-23",
"cinStatus": "ACTIVE",
"email": "[email protected]",
"incorporationCountry": "INDIA",
"directorDetails": [
{
"din": "07168822",
"name": "Frank Kelvin",
"dob": "1997-07-21",
"designation": "DIRECTOR",
"address": "ST BED KORAMANGALA, BANGALORE, KARNATAKA, INDIA, 566634"
},
{
"din": "07168826",
"name": "John Doe",
"dob": "1997-02-07",
"designation": "DIRECTOR",
"address": "GAUTAM NAGAR, NOIDA, UTTAR PRADESH, INDIA, 211361"
}
],
"companyStatus": "ACTIVE",
"directors": [
{
"din": "07168822",
"name": "Frank Kelvin",
"designation": "DIRECTOR"
},
{
"din": "07168826",
"name": "John Doe",
"designation": "DIRECTOR"
}
]
}POST /v1/verify/cinCompany CIN: ₹5 per successful call, pay-as-you-go (lower on Growth and Scale).
GSTIN
POST /v1/verify/gstinRequest parameters
| Field | Type | Description |
|---|---|---|
Authorizationrequired | header | Bearer <api-key> (e.g. sk_test_... in sandbox, sk_live_... in production). The x-api-key header is also accepted. |
gstinrequired | string | 15-character GSTIN, format 07AAAAA1111A1Z1. |
businessName | string | Business (legal or trade) name to cross-check against the registration. |
POST /v1/verify/gstin{
"referenceId": "SMV-20260927-9K21P4",
"verificationId": "VRF-4M8Q2T7XB9KD",
"gstin": "29AAICP2912R1ZR",
"GSTIN": "29AAICP2912R1ZR",
"valid": true,
"legalNameOfBusiness": "UJJIVAN SMALL FINANCE BANK LIMITED",
"tradeNameOfBusiness": "UJJIVAN SMALL FINANCE BANK",
"centerJurisdiction": "I-A RANGE",
"stateJurisdiction": "GUWAHATI - A - 1",
"dateOfRegistration": "2017-09-30",
"constitutionOfBusiness": "Public Limited Company",
"taxpayerType": "Regular",
"gstinStatus": "Active",
"lastUpdateDate": "2022-03-01",
"natureOfBusinessActivities": [
"Retail Business",
"Supplier of Services",
"Recipient of Goods or Services",
"Office / Sale Office",
"Others"
],
"principalPlaceAddress": "First Floor 3512-DISPUR Prithivi Mansion opp. KFC building G.S. Road, Lachit Nagar Assam 781007",
"principalPlaceSplitAddress": {
"buildingName": "Prithivi Mansion",
"street": "G.S. Road",
"location": "Lachit Nagar",
"buildingNumber": "3512-DISPUR",
"district": "Guwahati",
"state": "Assam",
"city": "Dispur",
"flatNumber": "First Floor",
"latitude": "26.1445",
"longitude": "91.7362",
"pincode": "781007"
},
"additionalAddresses": [
{
"address": "Mirza Santipur NH-37 Dist-Kamrup Rural PS-Palashbari, PO Mirza Kamrup Assam 781125",
"splitAddress": {
"buildingName": "",
"street": "NH-37",
"location": "Santipur, Mirza",
"buildingNumber": "",
"district": "Kamrup Rural",
"state": "Assam",
"city": "Palashbari",
"flatNumber": "",
"latitude": "26.0926",
"longitude": "91.5069",
"pincode": "781125"
}
},
{
"address": "N.A.C.C.I. Foundation 3559-Tezpur CHAMBER BHAWAN Binjraj Road, P. o. and P.S. - Tezpur, Dist. Binjraj Road, P. o. and P.S. - Tezpur, Dist. Sonitpur Assam 784154",
"splitAddress": {
"buildingName": "CHAMBER BHAWAN",
"street": "Binjraj Road",
"location": "Tezpur",
"buildingNumber": "3559-Tezpur",
"district": "Sonitpur",
"state": "Assam",
"city": "Tezpur",
"flatNumber": "",
"latitude": "26.6338",
"longitude": "92.8006",
"pincode": "784154"
}
}
],
"message": "GSTIN Exists",
"legalName": "UJJIVAN SMALL FINANCE BANK LIMITED",
"tradeName": "UJJIVAN SMALL FINANCE BANK",
"registrationStatus": "Active",
"principalPlaceOfBusiness": "First Floor 3512-DISPUR Prithivi Mansion opp. KFC building G.S. Road, Lachit Nagar Assam 781007"
}POST /v1/verify/gstinGSTIN: ₹5 per successful call, pay-as-you-go (lower on Growth and Scale).
Udyam Registration
POST /v1/verify/udyamRequest parameters
| Field | Type | Description |
|---|---|---|
Authorizationrequired | header | Bearer <api-key> (e.g. sk_test_... in sandbox, sk_live_... in production). The x-api-key header is also accepted. |
udyamNumberrequired | string | Udyam Registration Number (URN), format UDYAM-MH-12-1234567. |
POST /v1/verify/udyam{
"referenceId": "SMV-20260927-5U29V7",
"verificationId": "VRF-7K3M9Q2XH4TB",
"found": true,
"status": "SUCCESS",
"udyamStatus": "SUCCESS",
"udyamNumber": "UDYAM-UP-43-1234567",
"enterpriseName": "helloscholar",
"organizationType": "Proprietary",
"majorActivity": "Services",
"socialCategory": "General",
"dateOfIncorporation": "2020-05-29",
"dateOfCommencement": "2020-05-29",
"dateOfUdyamRegistration": "2022-01-02",
"enterpriseType": "Micro",
"classificationYear": "2024-25",
"classificationDate": "2025-06-02",
"certificateUrl": "https://udyamregistration.gov.in/Udyam_Download/UDYAM-UP-43-1234567.pdf",
"classificationHistory": [
{
"serialNumber": "1",
"classificationYear": "2024-25",
"enterpriseType": "Micro",
"classificationDate": "2025-06-02"
},
{
"serialNumber": "2",
"classificationYear": "2023-24",
"enterpriseType": "Micro",
"classificationDate": "2023-05-09"
},
{
"serialNumber": "3",
"classificationYear": "2022-23",
"enterpriseType": "Micro",
"classificationDate": "2022-06-26"
}
],
"splitAddress": {
"flat": "Ground Floor",
"building": "05 Raman Vihar",
"village": "Naubasta",
"block": "Naubasta",
"street": "Naubasta",
"city": "Kanpur",
"district": "KANPUR NAGAR",
"state": "UTTAR PRADESH",
"pincode": "208021",
"mobile": "70*****210",
"email": "[email protected]"
},
"unitLocations": [
{
"serialNumber": "1",
"unitName": "hellobanker",
"flat": "Ground Floor",
"building": "05 Raman Vihar Naubasta",
"village": "KANPUR NAGAR",
"block": "KANPUR NAGAR",
"street": "05 Raman Vihar Naubasta Bamba",
"city": "Kanpur",
"district": "KANPUR NAGAR",
"state": "UTTAR PRADESH",
"pincode": "208021"
},
{
"serialNumber": "2",
"unitName": "helloscholar",
"flat": "Ground Floor",
"building": "05 Raman Vihar Naubasta",
"village": "Kanpur",
"block": "Kanpur",
"street": "Kanpur",
"city": "Kanpur",
"district": "KANPUR NAGAR",
"state": "UTTAR PRADESH",
"pincode": "208021"
}
],
"nicCodes": [
{
"serialNumber": "1",
"nic2Digit": "85",
"nic2Description": "Education",
"nic4Digit": "8550",
"nic4Description": "Educational support services",
"nic5Digit": "85500",
"nic5Description": "Educational support services",
"activity": "Services",
"date": "2022-01-02"
}
],
"dic": "KANPUR NAGAR",
"msmeDi": "KANPUR"
}POST /v1/verify/udyamUdyam Registration: ₹5 per successful call, pay-as-you-go (lower on Growth and Scale).
PAN to GSTIN
POST /v1/verify/pan-to-gstinRequest parameters
| Field | Type | Description |
|---|---|---|
Authorizationrequired | header | Bearer <api-key> (e.g. sk_test_... in sandbox, sk_live_... in production). The x-api-key header is also accepted. |
panrequired | string | PAN to resolve to associated GSTIN(s). |
POST /v1/verify/pan-to-gstin{
"referenceId": "SMV-20260927-1L67Z5",
"found": true,
"gstins": [
{
"gstin": "07AAAAA1111A1Z1",
"state": "Delhi",
"status": "Active"
}
]
}POST /v1/verify/pan-to-gstinPAN to GSTIN: ₹5 per successful call, pay-as-you-go (lower on Growth and Scale).
Frequently asked questions
What is the difference between KYB and KYC?
KYC checks a person; KYB checks a legal entity and the people connected to it. A KYB program normally includes KYC-style checks on the signatory or proprietor, plus registry checks on the entity: PAN, GSTIN, CIN or Udyam, their status, and whether they agree with each other.
Which checks are free before calling the API?
Pattern checks, the PAN inside a GSTIN against the PAN you hold, and the GSTIN state code against the declared state need no API call. After a CIN response, the year inside the CIN can also be compared with the incorporation date.
Does the CIN response tell me who owns the company?
No. It lists directors with DIN, name and designation, which helps reviewers recognise the people and compare the signatory. Ownership and beneficial ownership are established from documents and your own judgement, under the rules that apply to your regulator and policy.
How should LLPs and partnership firms be verified?
There is no CIN-style endpoint for an LLP on this platform, so use the entity PAN, the GSTIN where registered and the bank account, check at least the signatory as an individual, and ask for the documents your policy requires, such as a registration certificate.
How do we decide credit limits from KYB results?
Score the verified signals and map score and exposure to tiers. Full evidence of PAN, registration, signatory and bank account supports higher limits and credit terms, while partial evidence supports low limits and prepayment. Record the rule version with each decision and change the rule, not the reviewers.
Why monitor businesses after onboarding?
Registrations get cancelled, companies get struck off and accounts close after onboarding. Re-check status by risk tier on a schedule, and on triggers such as returned payments, account or signatory changes and disputes. Monitoring surfaces the change; the risk team decides what to do about exposure.
What if a business has no GSTIN or CIN?
Use a lighter path: the proprietor's PAN with name and a bank account in their name, or documents reviewed by a person for trusts and societies. Assign a low tier with low limits or prepayment, instead of rejecting legitimate small businesses.
How should name differences between registers be handled?
Normalise suffixes and punctuation, compare token overlap instead of equality, and make the result a finding with severity. A high overlap passes, a middling overlap goes to review with both names, and a low overlap is a hard finding only together with another inconsistency.
What does KYB cost per business?
A company with PAN, GSTIN, CIN, a signatory PAN and a bank account costs four standard calls plus one bank check at your plan's rates, and a sole proprietor costs two standard calls plus a bank check. The page shows the arithmetic per plan before 18 percent GST.
Do verification calls notify us when a registration changes?
No. Verification endpoints are synchronous request and response, and webhooks on this platform cover order lifecycle events. To watch for changes, run scheduled re-checks of status and store each referenceId, then decide what a change means for exposure.
Sources
- StampMitra verification API reference, pricing page and sandbox documentation on developer.stampmitra.in (read 2026-10-29).
- PAN holder-type character, GSTIN structure and CIN structure are described from general knowledge of the Indian identifier formats and were not re-checked against official portals for this page in 2026; confirm before building strict rules on them.
- The Digital Personal Data Protection Act, 2023, India Code: https://www.indiacode.nic.in/handle/123456789/22037?view_type=browse (located 2026-10-16 in this site's KYC guide; confirm the current status of the rules against the official text).
- StampMitra Developer Data Retention and Deletion Schedule and Data Processing Addendum.