A vehicle RC verification API takes a registration number such as MH12AB1234 and returns the registration certificate details held against it: registration status, owner name, vehicle class, make and model, chassis and engine numbers, registration date, RC expiry and an insurance-validity date. With StampMitra you send one POST to /v1/verify/rc with a vehicleNumber, using an API key that carries the verification.rc.read scope, and you get back a JSON object that also includes a referenceId for your audit trail.
The call is simple. The hard part is everything around it: normalising what users type, deciding which returned fields should block a transaction, keeping owner details out of logs, and restricting which servers can use a key that reads personal data. This guide walks through all of it with real request and response bodies, Node.js and Python samples, sandbox testing, the production approval path and a troubleshooting table.
It is written for developers building fleet onboarding, vehicle-backed lending, motor insurance journeys and used-vehicle marketplaces in India. It is general information, not legal advice, and StampMitra is a private LegalTech platform operated by Bani Global Industries LLP, not a government agency.
Key takeaways
- Endpoint:
POST https://api-b2b.stampmitra.in/v1/verify/rc, body{ "vehicleNumber": "MH12AB1234" }, scopeverification.rc.read. - The response carries the registration status, owner name, owner's father's name, class, make, model, colour, chassis, engine, registration date,
rcStatus,rcExpiryDate,insuranceUpto,isCommercialand a StampMitrareferenceId. - Normalise input before sending (uppercase, strip spaces and hyphens). A malformed number fails fast with a
400and is never submitted for verification. - Treat the response as a point-in-time snapshot. Store the
referenceIdand the decision, not a copy of the whole owner record. - Owner name and father's name are personal data. Collect only for a stated purpose, with the notice and consent your lawyers advise, and keep them out of application logs.
- RC keys are sensitive: StampMitra pages say sensitive scopes such as RC default to requiring an IP/CIDR allowlist. Use one key per service with only the scopes it needs.
- Pair RC with Driving Licence verification for fleet driver checks and with PAN verification when the owner is your borrower.
- Sandbox is free and never debits your wallet. Production needs an approved application and a funded API credit wallet.
What does a vehicle RC verification API return?
A registration certificate (RC) is the document that records a vehicle against its registered owner. An RC verification API turns that record into structured data you can check in code, so nobody has to photograph a card, squint at a scan or call a transport office.
StampMitra's rc product returns the fields below. They are taken directly from the response example in the product data behind the Vehicle RC documentation.
| Field | Example | What you use it for |
|---|---|---|
referenceId | SMV-20260927-3D71Q9 | StampMitra transaction id (format SMV-YYYYMMDD-XXXXXXX). Store it for audits and support |
regNo | MH12AB1234 | The registration number the record is held against |
registrationStatus | VALID | Whether the registration is currently valid |
ownerName | RAHUL KUMAR | Match against the person or entity you are onboarding |
ownerFatherName | SURESH KUMAR | Secondary match signal, also personal data |
vehicleClass | LMV | Category of vehicle, relevant to permitted use and licence class |
vehicleManufacturerName | MARUTI SUZUKI | Make |
model | SWIFT | Model |
vehicleColor | WHITE | Quick physical sanity check at inspection |
chassis | MA3ERLF1S00123456 | Match to the chassis plate or an inspection report |
engine | K12MN1234567 | Match to the engine number on the vehicle |
registrationDate | 2019-05-14 | Vehicle age, depreciation and eligibility rules |
rcStatus | ACTIVE | Status of the certificate itself |
rcExpiryDate | 2034-05-13 | Date the RC validity runs to |
insuranceUpto | 2025-05-13 | Insurance validity date as returned |
isCommercial | false | Whether the vehicle is registered as commercial |
Two things are worth noticing. First, registrationStatus and rcStatus are separate fields, and a sensible integration reads both rather than assuming they always agree. Second, the owner-related fields are the sensitive part of this payload. Everything else describes a machine; those two describe a person.
What the response does not tell you
An RC lookup is a record check. It does not prove that the person in front of you is the owner, that the vehicle is physically where they say it is, that no loan is hypothecated against it, or that the insurance policy is genuinely in force at the insurer. The product data does not document fields for hypothecation or pending challans, so do not build logic that depends on them. If your decision needs those facts, collect them from the lender, the insurer or the relevant authority in a separate step.
How is an Indian vehicle registration number structured?
Registration marks in India follow a recognisable pattern: letters for the state, a number for the registering authority (district or regional office), one or two series letters, and a four-digit number. The sample number in the StampMitra product data, MH12AB1234, fits that pattern, and the validation message the endpoint returns for bad input reads "vehicleNumber must match the format MH12AB1234".
| Segment | Sample | Meaning |
|---|---|---|
| State or UT code | MH | Two letters for the state or union territory of registration |
| Registering authority number | 12 | Two digits identifying the registering office within that state |
| Series | AB | Letters that advance as numbers in a series are used up |
| Number | 1234 | Four-digit running number |
The Central Motor Vehicles Rules, 1989 govern how registration marks are displayed. In the sources we could read for this guide, Rule 50 is described as requiring English letters and Arabic numerals, with the mark arranged on the plate in lines, and with a different background colour scheme for transport vehicles. For the authoritative text, read the current rules on the Ministry of Road Transport and Highways (MoRTH) website, and for registration practice read Parivahan. Rules get amended, so check the date on whatever version you rely on.
Formats your input handling must expect
The tidy four-part shape hides real-world variety. Plates are printed with spaces (MH 12 AB 1234), people type hyphens, and older series have one letter or none. Reports describe a separate Bharat (BH) series, introduced by a MoRTH notification in August 2021, where the mark begins with the year of first registration followed by BH, a four-digit number and two letters, for example 22 BH 1234 AA. We could not open the notification itself while preparing this guide, so treat that description as secondary and verify it before relying on it.
The practical consequence is that you should not write your own strict regular expression and reject numbers on that basis. The StampMitra endpoint validates the format server-side. Do light normalisation on your side (uppercase, remove spaces, hyphens and dots), then let the API be the judge. If you operate in a segment where BH-series vehicles are common, such as corporate fleets with employees posted across states, test a BH-series number in sandbox first and see how the endpoint responds, because the product data only documents the MH12AB1234 style.
Why format validation fails fast
The product notes state that input format is validated up front and that a malformed value fails with a 400 instead of being submitted for verification. That matters for cost and latency: a typo in a form never turns into a billable lookup. It also means your UI should display the returned message, which names the field, so users can fix it.
What does the StampMitra RC endpoint look like?
The contract is deliberately small. Everything below comes from the rc entry in the product data.
| Property | Value |
|---|---|
| Method and path | POST /v1/verify/rc |
| Base URL | https://api-b2b.stampmitra.in |
| Auth | Authorization: Bearer <api-key>, or the x-api-key header |
| Scope required | verification.rc.read |
| Body | vehicleNumber (string, required) |
| Metered as | rc.verify, recorded after a successful response |
| Sandbox key prefix | sk_test_ |
| Production key prefix | sk_live_ |
Per-call pricing is ₹9 for RC in production; sandbox calls are free. Usage is recorded, and the fulfilment wallet debited for priced services, only once verification completes successfully.
A first request
curl -X POST "https://api-b2b.stampmitra.in/v1/verify/rc" \
-H "Authorization: Bearer $STAMPMITRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"vehicleNumber":"MH12AB1234"}'The response
{
"referenceId": "SMV-20260927-3D71Q9",
"regNo": "MH12AB1234",
"registrationStatus": "VALID",
"ownerName": "RAHUL KUMAR",
"ownerFatherName": "SURESH KUMAR",
"vehicleClass": "LMV",
"vehicleManufacturerName": "MARUTI SUZUKI",
"model": "SWIFT",
"vehicleColor": "WHITE",
"chassis": "MA3ERLF1S00123456",
"engine": "K12MN1234567",
"registrationDate": "2019-05-14",
"rcStatus": "ACTIVE",
"rcExpiryDate": "2034-05-13",
"insuranceUpto": "2025-05-13",
"isCommercial": false
}The referenceId is always present on a completed call. It is StampMitra's own transaction id and, per the product notes, it is not an idempotency key. Do not assume that retrying with the same id returns the same result; the verify route documents no Idempotency-Key header, so design retries to tolerate a repeated call.
How do you verify a vehicle RC step by step?
The sequence below is the shortest path from zero to a working integration. It follows the same flow as the 5-minute quickstart, swapping PAN for RC.
- Create a sandbox account. Sign up with email, mobile and password. You receive an
sk_test_key immediately, shown once. - Store the key as a secret. Put it in an environment variable such as
STAMPMITRA_API_KEY. Never ship it in a mobile app or browser bundle. The authentication docs cover both accepted headers. - Confirm the key has the right scope. The key must include
verification.rc.read. Keys created without choosing scopes get the environment defaults, so check the scope chips on the key in the dashboard. - Normalise the registration number. Uppercase it and strip spaces, hyphens and dots.
- Call
POST /v1/verify/rcfrom your server. Never from the client. - Read the result. Check
registrationStatus,rcStatus,rcExpiryDate,insuranceUptoandisCommercial, then match the owner and vehicle details against what the user told you. - Persist the minimum. Save
referenceId, the decision and the timestamp.
Node.js
// Node 18+ (built-in fetch)
const BASE = "https://api-b2b.stampmitra.in";
export function normaliseVehicleNumber(raw) {
return String(raw).toUpperCase().replace(/[\s.\-]/g, "");
}
export async function verifyRc(rawNumber) {
const res = await fetch(`${BASE}/v1/verify/rc`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.STAMPMITRA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ vehicleNumber: normaliseVehicleNumber(rawNumber) }),
});
const body = await res.json();
if (!res.ok) {
const { code, message, requestId } = body.error ?? {};
const err = new Error(message ?? `HTTP ${res.status}`);
err.status = res.status;
err.code = code;
err.requestId = requestId;
throw err;
}
return body;
}Python
import os
import re
import requests
BASE = "https://api-b2b.stampmitra.in"
def normalise_vehicle_number(raw: str) -> str:
return re.sub(r"[\s.\-]", "", raw.upper())
def verify_rc(raw_number: str) -> dict:
resp = requests.post(
f"{BASE}/v1/verify/rc",
headers={
"Authorization": f"Bearer {os.environ['STAMPMITRA_API_KEY']}",
"Content-Type": "application/json",
},
json={"vehicleNumber": normalise_vehicle_number(raw_number)},
timeout=20,
)
body = resp.json()
if not resp.ok:
err = body.get("error", {})
raise RuntimeError(f"{resp.status_code} {err.get('code')}: {err.get('message')} (requestId={err.get('requestId')})")
return bodyBoth samples surface the requestId from the error envelope. Log that, not the request body, and you will have what support needs without leaking a registration number and owner name into your log stream.
Which returned fields should drive your decision?
Having the data is not the same as having a rule. Most RC-based decisions boil down to four questions, and each maps to specific fields.
Is the vehicle validly registered?
Read registrationStatus and rcStatus together. In the sample both read as valid and active. Define in code exactly which values you accept, and send everything else to manual review rather than guessing at values the product data does not enumerate. An allow-list of known good values is safer than a block-list of known bad ones.
Is the RC still within its validity window?
Compare rcExpiryDate with today's date in India (IST), not the server's UTC date, when a decision hinges on the final day. The sample shows 2034-05-13, which is comfortably in the future. A date in the past, or within your minimum tenure for a loan, should block or escalate.
Is insurance in date?
The sample's insuranceUpto is 2025-05-13. Measured against today, 16 October 2026, that date is already in the past, so the sample record is a good test fixture for your "insurance lapsed" branch. Treat the field as an indicator, not as proof of cover: for a binding underwriting or claims decision, confirm the policy with the insurer.
Does the vehicle match what the user claimed?
Compare ownerName with the applicant's name using fuzzy matching, because records are upper-case and may abbreviate middle names. Compare chassis and engine with the inspection report or the plate. Compare isCommercial with the declared use: a vehicle registered as non-commercial offered for hire is a flag worth raising.
A small decision function
export function assessRc(rc, { declaredCommercial, minTenureDays = 0, today = new Date() }) {
const reasons = [];
if (rc.registrationStatus !== "VALID") reasons.push("registration_not_valid");
if (rc.rcStatus !== "ACTIVE") reasons.push("rc_not_active");
const daysToExpiry = (new Date(rc.rcExpiryDate) - today) / 86_400_000;
if (!(daysToExpiry > minTenureDays)) reasons.push("rc_expires_too_soon");
if (new Date(rc.insuranceUpto) < today) reasons.push("insurance_lapsed");
if (declaredCommercial !== undefined && rc.isCommercial !== declaredCommercial) {
reasons.push("commercial_flag_mismatch");
}
return { pass: reasons.length === 0, reasons, referenceId: rc.referenceId };
}Run against the sample response on 16 October 2026, this returns pass: false with insurance_lapsed, which is exactly the behaviour you want to see in a test. Keep the reasons as enumerated codes. They are far easier to audit than free text.
How do fleet operators and logistics platforms use RC verification?
Fleet onboarding is the cleanest use case because the verifier and the vehicle owner usually have a commercial relationship and a clear purpose for collecting the data.
Imagine a fictional marketplace, SwiftHaul Logistics, that lets small transporters join its network. A transporter submits a list of trucks. For each one, SwiftHaul needs to confirm that the registration is valid, that the vehicle is registered as commercial, and that the RC has not expired, before any load is assigned.
The onboarding flow
- The transporter enters or uploads registration numbers.
- Your backend normalises each number and calls
POST /v1/verify/rconce per vehicle. - For each response, you check
registrationStatus,rcStatus,rcExpiryDateandisCommercial. - Vehicles that pass are activated. Vehicles that fail go to a review queue with the reason codes.
- You store
referenceId, the decision and the check time.
Adding driver checks
A verified vehicle is only half of the picture. For drivers, StampMitra offers a Driving Licence verification endpoint at POST /v1/verify/driving-license, requiring the verification.dl.read scope and two fields: dlNumber and dob in YYYY-MM-DD. The sample response includes valid, name, fatherOrHusbandName, dob, address, validUpto and dlStatus. Per-call pricing is ₹5.
curl -X POST "https://api-b2b.stampmitra.in/v1/verify/driving-license" \
-H "Authorization: Bearer $STAMPMITRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"dlNumber":"MH1420110012345","dob":"1990-01-01"}'A sensible rule is to pair each vehicle with the driver assigned to it and verify both on onboarding. Match the driver's name from the licence with the name the driver gave you. Whether the licence class suits the vehicle class is a business rule you will need to define with your compliance team, since the product data does not map licence classes to vehicle classes for you.
Re-verification
Fleet data decays. RC expiry and insurance dates move, vehicles get sold, drivers change. Decide a re-check cadence, for example before each contract renewal or when a stored expiry date is within a set number of days, and run it as a scheduled job. Because every successful call is billed, drive re-checks off dates you already hold instead of polling the whole fleet daily.
Matching owner names without false rejections
Names in registration records are upper-case and may be stored as initials plus surname, with or without a middle name, and spelling varies across regions. A strict equality check will reject honest applicants. Normalise both sides (uppercase, remove punctuation, collapse spaces), compare token sets, and use a similarity threshold your risk team signs off on. Anything between a clear match and a clear mismatch should go to a human, with both names displayed side by side. Measure your false-reject rate for the first month in production and tune the threshold using real review outcomes, not guesses.
How do lenders, insurers and used-vehicle marketplaces use it?
These three segments share one trait: money moves on the strength of the vehicle record, so the cost of a wrong decision is higher than in fleet onboarding.
Lending against vehicles
A fictional NBFC, Kaveri Wheels Finance, offers loans against two-wheelers and cars. At application it asks for the registration number, the borrower's PAN and the borrower's name. The flow is typically:
- Verify the borrower's identity with PAN verification and the name-match option.
- Verify the vehicle with the RC endpoint.
- Compare
ownerNamefrom the RC with the verified registered name from the PAN response. A mismatch might mean the vehicle belongs to a relative, which changes the security position. - Check
registrationDateagainst the lender's vehicle-age policy, andrcExpiryDateagainst the loan tenure. - Record
referenceIdvalues from both checks against the application.
The RC response tells you who the registered owner is. It does not show whether another lender already holds a charge on the vehicle, because the product data documents no such field. Keep your existing hypothecation checks. For the wider lending stack, see the KYC API use case for fintech and NBFCs.
Motor insurance
Insurers and brokers can prefill a quote from the registration number: make, model, class, registrationDate, chassis and engine map to rating inputs, and the user avoids typing them. Because insuranceUpto is returned, a renewal journey can detect an imminent or lapsed date. Show the prefilled values back to the user for confirmation, because rating errors cause claim disputes later.
Used-vehicle marketplaces
A dealer-listing platform can verify each listing at upload: does the plate exist, is the colour and model what the seller says, and does ownerName correspond to the seller or the dealer entity? Mismatches between the listing and the RC (wrong colour, wrong model, chassis that does not match the photographed plate) are classic listing-fraud signals. For dealers incorporated as companies, combine the RC check with business verification using GSTIN, CIN and Udyam. In all three segments, a failed check should open a manual review, not an automatic accusation of fraud.
How should you protect owner details from an RC lookup?
The RC response contains the owner's name and the owner's father's name. Combined with a registration number, that is personal data about an identifiable individual, and handling it casually is the fastest way to create a compliance problem.
The Digital Personal Data Protection Act, 2023 is India's central data-protection statute. We could not open the official text of the Act while preparing this guide, so the points below are general good practice that secondary summaries consistently attribute to it: process personal data for a lawful purpose, generally on the basis of consent or a defined legitimate use; give a clear notice of what is collected and why; keep the data accurate and secure; erase it when the purpose is served; and have a way to handle complaints and report breaches. Which provisions apply to you, and when each takes effect under the rules made under the Act, are questions for qualified counsel. Read the Act and its rules directly before you finalise your design.
Practical controls
- Purpose limitation. Decide why you run the lookup (for example, to confirm a vehicle before assigning a load) and do not reuse the owner details for marketing or unrelated scoring.
- Notice and consent. Tell the person, in plain language, that you will check their vehicle record and why. Capture the consent artefact your counsel recommends and keep it linked to the
referenceId. - Minimise what you store. In most flows you need the decision, the reason codes, the vehicle identifiers and the
referenceId, not a permanent copy ofownerNameandownerFatherName. If you must store them, set a retention period and delete on schedule. - Keep it out of logs. Do not log full request or response bodies at INFO level. Log
requestId,referenceIdand status codes. - Mask in the UI. Support agents rarely need the father's name. Show it only to roles that do.
- Encrypt at rest and in transit. The API is HTTPS. Encrypt your own datastore and restrict who can read it.
- Limit who can call the API. See the next section on scopes and IP allowlisting.
StampMitra publishes its own terms on this: the Developer Privacy Policy, the Data Processing Addendum and the API Acceptable Use Policy. Read them with your counsel, because they set out what you may use verification results for.
How do scopes and IP allowlisting work for RC keys?
Every StampMitra API key is environment-scoped and carries a list of OAuth-style scopes that gate individual endpoints. For RC, the scope is verification.rc.read. A valid key without that scope receives a 403 FORBIDDEN with the message "API key is valid but lacks the required scope for this endpoint."
Scope hygiene
- Create separate keys per service. The service that onboards vehicles needs
verification.rc.readand perhapsverification.dl.read. It does not needorders.createorpayments.write. - When creating a key in the dashboard, you can pick scopes. If you select none, the environment's default scopes apply, which may be broader than you want. Choose explicitly.
- Rotate keys when staff leave and after any suspected exposure. A rotate action revokes the old key and issues a new one, and the raw key is only ever shown once.
IP allowlisting
The authentication documentation says sensitive scopes can additionally be restricted to an IP allowlist, and the StampMitra home page says a key can be restricted to an IP/CIDR list and that sensitive scopes like PAN and RC default to requiring one. In plain terms: a key that can read owner details should work only from the servers you expect.
Practical steps:
- List the egress IPs of the service that will call RC. If you run behind a NAT gateway, that is its public address range.
- Configure those addresses or CIDR ranges against the key. The product data does not document an API for this, so use the dashboard or ask support if you cannot find the setting.
- Test from a non-allowlisted network and confirm that the call is refused. The product data does not state which status code a blocked IP receives, so observe it in sandbox and handle it explicitly.
- Plan for change. Serverless platforms and autoscaled clusters may not have stable egress addresses. Put a fixed-egress proxy or NAT in front of calls to RC, instead of loosening the allowlist.
Never call from the browser
Because the key is the credential, calling RC directly from a web or mobile client exposes it and defeats IP restrictions. Always call your own backend, which in turn calls StampMitra. The API Security Policy describes the platform's side of the arrangement.
What errors can the RC endpoint return, and how should you handle them?
Every error from the API uses one envelope, produced by the platform's global exception filter: { "error": { "code", "message", "requestId" } }. These are the cases documented for the verify routes.
| Status | code | Message in product data | Meaning and action |
|---|---|---|---|
| 400 | BAD_REQUEST | vehicleNumber must match the format MH12AB1234 | Input failed format validation. Show the message, let the user correct it, do not retry unchanged |
| 401 | UNAUTHORIZED | Missing or invalid API key. | Check the header, the environment and that the key is not revoked |
| 402 | PAYMENT_REQUIRED | Insufficient fulfilment wallet balance to cover this call. | Top up the API credit wallet, then retry |
| 403 | FORBIDDEN | API key is valid but lacks the required scope for this endpoint. | Add verification.rc.read to the key or use a key that has it |
| 429 | TOO_MANY_REQUESTS | Rate limit exceeded: 60 requests per 60 seconds for this endpoint. | Back off and retry; also seen when a sandbox quota is exceeded |
| 502 | INTERNAL_ERROR | Unable to reach the order/customer service right now | Upstream verification service unreachable; retry with backoff |
The 429 example is the shared rate-limit message in the product data and is not listed individually under the RC route, so confirm the live limit for your key rather than hard-coding 60 per 60 seconds. For a broader treatment of the pattern, see the guide to API errors and handling.
A retry policy that fits
Retry 502 and 429 with exponential backoff and jitter, and cap attempts. Do not retry 400, 401, 403 or 402 automatically, because retrying without a change will fail the same way. The requestId in each error body is what support will ask for.
const RETRYABLE = new Set([429, 502]);
export async function verifyRcWithRetry(number, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await verifyRc(number);
} catch (err) {
if (!RETRYABLE.has(err.status) || i === attempts - 1) throw err;
const wait = 500 * 2 ** i + Math.random() * 250;
await new Promise((r) => setTimeout(r, wait));
}
}
}What about "no such vehicle"?
The product data documents a successful response shape and the error cases above. It does not document a separate response for a number that is well-formed but has no record. Do not guess: run a few unregistered but well-formed numbers in sandbox, record exactly what comes back, and code against that observed behaviour. Remember that, per the product notes, completed negative determinations for verification products are billable in production.
How do you test RC verification in sandbox?
Sandbox keys use the sk_test_ prefix and run against sandbox data. Sandbox calls are metered and logged, but they never debit your wallet, so you can test without risk. The environment is resolved server-side from the key, so the same request shape and base URL work in both environments.
The site describes the sandbox allowance in two ways (a lifetime call quota on one page, unlimited test-mode calls on another), and going over a quota returns a clear 429. Check your dashboard for the allowance on your account, and do not burn it with load tests.
What to test
| Scenario | How | Expected |
|---|---|---|
| Happy path | Send MH12AB1234 | 200 with the sample-shaped body and a referenceId |
| Messy input | Send mh 12 ab-1234 after normalising | Same as happy path |
| Malformed input | Send 1234 or an empty string | 400 BAD_REQUEST naming vehicleNumber |
| Missing key | Omit the header | 401 UNAUTHORIZED |
| Wrong scope | Use a key without verification.rc.read | 403 FORBIDDEN |
| Insurance lapsed | Use the sample response in a unit test | Your logic returns insurance_lapsed |
| Upstream failure | Mock a 502 in your HTTP client | Your retry policy engages |
| IP restriction | Call from a non-allowlisted host | Request refused; record the code |
Use fixtures, not live calls, for logic tests
Your decision logic (assessRc above) should be tested with fixture JSON, not by calling the API. Save the documented sample body as a fixture, then derive variants by editing fields: expired RC, inactive status, commercial mismatch. Reserve live sandbox calls for contract tests that prove authentication, scopes, headers and error handling. If you work with AI coding tools, the MCP server and the Postman collection let you exercise sandbox calls without writing code first. For more on the difference between key types, read sandbox vs production API keys.
How do you go live with RC verification?
Production is gated per product. You apply from the dashboard for the APIs you want to take live, and each one is reviewed before a production key is issued. The dashboard notes that production access requires additional account and use-case verification, and the application asks you to describe your use case. Write a specific description. "Verify vehicle registration of transporters before assigning loads on our logistics marketplace" will do better than "KYC".
Go-live checklist
- Apply for production access for the RC product (service code
rc.verify). You can follow its status in the dashboard. - Prepare your purpose and consent story, because reviewers and, later, your own auditors will ask why you need owner details.
- Create a production key (
sk_live_) once approved, scoped toverification.rc.readonly, ideally with an IP allowlist. - Fund the API credit wallet. Production calls are deducted from it at the per-call rate on the pricing page. A
402means the balance is too low. - Swap the key in your secrets manager. The code is unchanged; only the key differs. Keep the sandbox key for staging.
- Alert on
402,429and502rates. A depleted wallet at 2 a.m. should page someone before customers notice. - Review logs for personal data before launch. Run a search for owner names in your log store.
Keep costs predictable
Billing happens after a successful response, so format errors, auth errors and failures to reach the upstream do not consume credit, based on the product notes. Cache the decision, not the owner details, for a window your risk team accepts, so that a user who retries a form does not trigger repeated lookups. Where freshness matters, such as at disbursal, make a fresh call.
Monitoring after launch
The first weeks in production show you how real users type registration numbers. Track the share of requests that end in a 400, because a high rate points to a form problem rather than a user problem: add input hints, an example plate, and live normalisation as the user types. Track the median and 95th percentile latency of the call, since your users wait on it, and set a client timeout so a slow upstream does not hang a checkout. Track wallet balance against daily call volume so you can see days of runway at a glance. Finally, review a sample of manual-review cases each week with your risk team to confirm the reason codes still make sense, because a rule that was right at launch can drift as your customer mix changes.
When should you use RC verification, and when should you not?
RC verification is a strong fit when a vehicle record is a precondition to a transaction and you have a legitimate, stated purpose for reading it. It is a poor fit when you are looking for something the record cannot tell you.
| Situation | Use RC verification? | Why |
|---|---|---|
| Onboarding commercial vehicles to a marketplace | Yes | Confirms registration, class and commercial flag |
| Pre-sanction check on a vehicle-backed loan | Yes, plus other checks | Confirms owner and RC validity; add lien checks separately |
| Prefilling a motor insurance quote | Yes | Reduces typing errors in rating inputs |
| Vetting a used-vehicle listing | Yes | Cross-checks seller claims against the record |
| Proving the person is the owner | No, not alone | The record shows the registered owner, not who is in front of you |
| Confirming a live insurance policy for a claim | No, not alone | insuranceUpto is an indicator; confirm with the insurer |
| Finding who owns a random vehicle you saw | No | No lawful purpose; violates acceptable use |
| Bulk data enrichment with no consent or purpose | No | Breaches purpose limitation and the acceptable use policy |
Choosing between RC, DL and business checks
- Need to verify the vehicle? Use RC.
- Need to verify the driver? Use Driving Licence, which requires the date of birth.
- Verifying an individual owner or borrower? Add PAN.
- Verifying a transport company? Use GSTIN, CIN or Udyam through the business verification guide.
Questions to ask before you build
Do you have a stated purpose? Will users be told? Can you do the job without storing owner details? Who will see the data? If any answer is unclear, resolve it before writing code.
How should you store and audit RC results?
An audit trail answers one question months later: why did we approve or reject this vehicle? You can answer it without hoarding owner details, provided you design the record deliberately.
What a good audit record holds
Keep a compact row per lookup: your internal case id, the StampMitra referenceId, the timestamp, the normalised regNo, the decision, the enumerated reason codes from your assessment function, and the version of your rules. That is enough to reconstruct the decision and to give StampMitra support something precise to trace if a result is disputed. The referenceId follows the SMV-YYYYMMDD-XXXXXXX shape, so it also sorts naturally by date.
If your regulator, auditor or lender contract requires you to retain the source response, store it in a separate, encrypted, access-controlled table with a retention date, not alongside everyday application data. Treat that table as personal data from day one: restrict reads to a small role, log every access, and delete rows when the retention period ends.
Handling disputes and corrections
Owners change, records are corrected, and a vehicle that failed last month may pass today. Build the workflow so that a new lookup creates a new audit row instead of overwriting the old one. When a customer disputes a rejection, you can then show the original result, the later result and the reason the decision changed. Do not edit stored responses by hand.
A simple schema
CREATE TABLE rc_checks (
id BIGSERIAL PRIMARY KEY,
case_id TEXT NOT NULL,
reference_id TEXT NOT NULL, -- StampMitra referenceId
reg_no TEXT NOT NULL,
decision TEXT NOT NULL, -- pass | review | reject
reasons TEXT[] NOT NULL DEFAULT '{}',
rules_version TEXT NOT NULL,
checked_at TIMESTAMPTZ NOT NULL DEFAULT now()
);Notice what is missing: no owner name, no father's name. If a downstream team insists they need the owner name, ask what for, and whether a match score would do instead.
Sharing results internally
Support, risk and operations teams often ask for screenshots of verification results. Resist forwarding raw JSON over chat or email. Give them a view that shows the decision, the reasons and the vehicle make and model, and only unmask the owner's name for roles that need it. This also makes your answer to an access review simple.
How do you troubleshoot common RC verification problems?
Most failures trace back to a short list of causes. Work down this table before contacting support.
| Symptom | Likely cause | Fix |
|---|---|---|
400 with the format message | Spaces, hyphens, lowercase or a typo in vehicleNumber | Normalise before sending; show the message to the user |
400 on a plausible BH-series plate | Format not covered by the documented example | Test in sandbox, then contact support with the requestId |
401 UNAUTHORIZED | Wrong header, truncated key, revoked key, or a sandbox key used against production expectations | Check Authorization: Bearer <key> or x-api-key; rotate if needed |
403 FORBIDDEN | Key lacks verification.rc.read | Create a key with the scope |
| Calls refused from a new server | Key is IP-restricted and the new egress IP is not listed | Add the address or CIDR range to the allowlist |
402 in production only | Wallet balance too low | Top up from the dashboard billing page |
429 bursts | Rate limit, or sandbox allowance used up | Add backoff and queueing; check dashboard allowance |
502 intermittently | Upstream verification service unreachable | Retry with backoff; check status and escalate with requestId |
| Owner name does not match the applicant | Abbreviations, initials, spelling, or a different legal owner | Use fuzzy matching with a threshold; route to review |
insuranceUpto in the past | Policy lapsed or record not yet refreshed | Treat as indicator; ask the user for the current policy |
| Results differ between two lookups | The record changed in between | Store the time with the referenceId and re-check at decision time |
Debugging habits that save time
Log requestId for every failure and referenceId for every success. Reproduce with cURL before blaming your SDK. Check which environment the key belongs to, because a sandbox key will not behave like a live one. If you are still stuck, write to [email protected] with the requestId, the time, the endpoint and the status code, and leave out owner details.
How StampMitra Helps
StampMitra gives developers a single REST layer for Indian verification and e-stamp workflows, and RC is one product within it. Today you can call POST /v1/verify/rc with a vehicleNumber, receive the registration, owner, vehicle, chassis, engine, RC expiry, insurance date and commercial flag in one JSON response, and get a referenceId back on every completed call. The same API key model covers Driving Licence, PAN, GSTIN and the other verification products, so a fleet or lending flow can use one integration, one error envelope and one wallet.
The security controls are the ones described in the platform's own pages: environment-scoped keys (sk_test_ and sk_live_), per-endpoint scopes such as verification.rc.read, per-key IP allowlisting, rate limits enforced server-side, and sandbox calls that never debit your wallet. Production is opt-in per product through an application that the StampMitra team reviews, and billing is per successful call from an API credit wallet at the rate published on the pricing page.
StampMitra is a private LegalTech platform operated by Bani Global Industries LLP. It is not a government agency, does not offer legal advice, and cannot guarantee any particular result from a lookup. The product data does not document hypothecation, challan or insurer-confirmed policy fields for RC, and this guide does not claim them. Use the product as one input into your own checks, and involve your counsel on consent and data-protection design.
For getting started, the Vehicle RC product page summarises the endpoint, the quickstart shows a first call end to end, and support handles integration questions. You can also use the MCP server and the Postman collection to try calls against sandbox.
What's next
These are plans, not commitments: client libraries for Node.js, Python, PHP, Java and Go are listed as planned on the SDKs page, and a self-serve webhook registration API is planned for order events. Neither is available today, so build against the REST API directly.
API reference at a glance
POST /v1/verify/rcRequest 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. |
vehicleNumberrequired | string | Vehicle registration number. |
POST /v1/verify/rc{
"referenceId": "SMV-20260927-3D71Q9",
"regNo": "MH12AB1234",
"registrationStatus": "VALID",
"ownerName": "RAHUL KUMAR",
"ownerFatherName": "SURESH KUMAR",
"vehicleClass": "LMV",
"vehicleManufacturerName": "MARUTI SUZUKI",
"model": "SWIFT",
"vehicleColor": "WHITE",
"chassis": "MA3ERLF1S00123456",
"engine": "K12MN1234567",
"registrationDate": "2019-05-14",
"rcStatus": "ACTIVE",
"rcExpiryDate": "2034-05-13",
"insuranceUpto": "2025-05-13",
"isCommercial": false
}POST /v1/verify/rcVehicle RC: ₹9 per successful call, pay-as-you-go (lower on Growth and Scale).
Frequently asked questions
What does a vehicle RC verification API return?
StampMitra returns registration status, owner name, owner's father's name, vehicle class, make, model, colour, chassis, engine, registration date, RC status, RC expiry date, insurance date, a commercial flag and a referenceId.
Which endpoint and scope does StampMitra use for RC verification?
Send a POST request to /v1/verify/rc on https://api-b2b.stampmitra.in with a vehicleNumber in the JSON body. The API key must carry the verification.rc.read scope or the call returns 403 FORBIDDEN.
What format should the vehicle registration number be in?
The documented example is MH12AB1234: state code, two-digit registering authority number, series letters and a four-digit number. Normalise input to uppercase without spaces or hyphens, and the API rejects malformed values with a 400.
Does the RC API prove who the owner is?
No. It returns the registered owner's details held against the registration number. It does not prove the person in front of you is that owner, so match names and add identity checks such as PAN where needed.
How should I protect the owner details in an RC response?
Collect them only for a stated purpose with the notice and consent your counsel advises, store the decision and referenceId instead of the owner name, keep them out of logs, mask them in the UI and set a retention period.
Does RC verification need an IP allowlist?
StampMitra pages say sensitive scopes such as RC default to requiring an IP or CIDR allowlist on the key. Configure the egress IPs of your backend, never call the API from a browser or mobile app, and test refusals in sandbox.
Can I test RC verification for free?
Yes. Sandbox keys start with sk_test_, run against sandbox data and never debit your wallet. Exceeding the sandbox quota returns a 429, so check your dashboard allowance and use fixtures for logic tests.
How do I go live with the RC API?
Apply for production access for the RC product from the dashboard with a specific use-case description. After review you can create an sk_live_ key, fund the API credit wallet and swap the key in your secrets manager.
What errors can the RC endpoint return?
The documented errors are 400 BAD_REQUEST for a malformed vehicleNumber, 401 UNAUTHORIZED, 402 PAYMENT_REQUIRED for low wallet balance, 403 FORBIDDEN for a missing scope, 429 TOO_MANY_REQUESTS and 502 INTERNAL_ERROR when upstream is unreachable.
Should I also verify the driver when I verify the vehicle?
For fleets, yes. StampMitra's Driving Licence endpoint needs a dlNumber and date of birth and the verification.dl.read scope, and lets you check the driver alongside the vehicle during onboarding.
Sources
Verified 2026-10-16. Where an official page could not be opened, that is stated and the claim is hedged in the text.
- StampMitra product data for the
rcanddriving-licenseverification products (src/data/api-products.ts): paths, scopes, parameters, response fields, error bodies, metering notes. Verified 2026-10-16. - StampMitra pages: Authentication, Pricing, Quickstart and the home page statements on IP allowlisting and sandbox. Verified 2026-10-16.
- Ministry of Road Transport and Highways, Central Motor Vehicles Rules, 1989, Rule 50 on registration marks, as described in search-result excerpts of state transport pages and MoRTH amendment notifications. The official pages returned errors when opened (2026-10-16), so format details are hedged. Check morth.gov.in for current text.
- Parivahan Sewa portal, parivahan.gov.in: returned HTTP 503 on 2026-10-16; cited as the place to check registration practice, not relied on for specific claims.
- Bharat (BH) series description (format
YY BH #### XX, MoRTH notification dated August 2021): secondary news and explainer sources only, not verified against the notification. - Digital Personal Data Protection Act, 2023: official text could not be opened (HTTP 403 on 2026-10-16); general principles described from secondary summaries and flagged for counsel review.