Loading…
Loading…
PUBLIC API V1
Authenticated HTTP APIs for IFSC lookup, GST calculation, and curated HSN/SAC classification. This site documents the v1 contract implemented in this repository. Public Cloud Functions are not yet deployed. The intended production host is https://mantechstudio.in.
Create an application in the Developer Console, issue a TEST key, and call /api/v1. Machine-readable contract: /openapi/openapi-v1.yaml. Try requests in the Playground.
Invoice extraction, AI classifiers, and ERP are not public HTTP APIs. Webhooks are signed delivery infrastructure, not a public resource catalog. OAuth client credentials are an optional authentication method for the same IFSC, GST, HSN, and SAC APIs — not Sign in with ManTech.
X-Request-Id and the X-RateLimit-* quota headers.curl "https://mantechstudio.in/api/v1/ifsc/SBIN0000691" \
-H "Authorization: Bearer mantech_test_0123456789abcdef.example_secret"const res = await fetch('https://mantechstudio.in/api/v1/ifsc/SBIN0000691', {
headers: { Authorization: 'Bearer mantech_test_0123456789abcdef.example_secret' }
});
const data = await res.json();
console.log(res.headers.get('x-request-id'), res.headers.get('x-ratelimit-remaining'));Public APIs authenticate an application in a test or live environment. Choose one credential:
Recommended: Authorization: Bearer … with either an API key or an OAuth access token. Supported: X-API-Key for API keys only (no access tokens on that header).
Authorization: Bearer mantech_test_0123456789abcdef.example_secretX-API-Key: mantech_test_0123456789abcdef.example_secretactive can authenticate. disabled and archived cannot. Inactive organization state also fails authentication.Developer Console management calls use a Firebase ID token. That is a different auth plane. Do not send a Firebase ID token to public data APIs, and do not send an API key or OAuth access token to /api/v1/developer/**.
OAuth is implemented in this repository and is not yet deployed. It is machine-to-machine service authorization, not OpenID Connect and not Sign in with ManTech. There is no authorization-code flow, PKCE, user consent, refresh token, or id_token.
Token endpoint: POST /oauth/token. Authenticate the client with HTTP Basic (client_id:client_secret). Body is application/x-www-form-urlencoded with grant_type=client_credentials and optional scope. Do not put the client secret in the query string or in browser JavaScript. CORS is disabled on the token endpoint because a browser cannot safely hold a client secret. Use HTTPS in deployed environments.
Access tokens last 900 seconds (15 minutes). They are opaque bearer credentials (mat_…). Protect them like secrets. Do not log them. Stolen tokens can be replayed until they expire or the client, application, or organization is disabled — verification re-checks that status on every API request. TEST clients mint TEST tokens and consume TEST quota. LIVE clients mint LIVE tokens. Environment cannot be chosen in the token request.
Registered scopes (identical to server capabilities): ifsc.read ifsc.search gst.calculate hsn.read hsn.search sac.read sac.search. Requested scopes must be a subset of the client allow-list; extra scopes are rejected. If scopeis omitted, all of the client's allowed scopes are granted. OAuth and API-key traffic for the same application and environment share one daily quota.
curl -X POST "https://mantechstudio.in/oauth/token" \
-H "Authorization: Basic $(printf '%s:%s' 'mcl_0123456789abcdef0123456789abcdef' 'mcs_example_not_a_real_secret' | base64 | tr -d '\n')" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&scope=ifsc.read"curl "https://mantechstudio.in/api/v1/ifsc/SBIN0000691" \
-H "Authorization: Bearer mat_example_not_a_real_token"error and error_description (for example invalid_client, invalid_scope). Public API errors keep the DP-03 envelope.whsec_) remain a separate credential. Do not reuse them as OAuth secrets.ManTech uses two API credential environments on the same /api/v1 base URL. The verified key selects the environment. There is no separate sandbox host and no fake IFSC, GST, HSN, or SAC dataset.
For current read-only/reference and deterministic calculation APIs (IFSC, GST, HSN, SAC), the underlying domain results are intentionally the same. The environment boundary exists so future state-changing APIs can isolate test activity from production activity.
Public Cloud Functions are not yet deployed. This documents the v1 contract implemented in this repository, including local/emulator verification.
Failed requests return a JSON envelope. param is optional. Retain request_id (also sent as X-Request-Id) when reporting a failure or contacting support. This is a correlation id, not distributed tracing.
{
"error": {
"type": "validation_error",
"code": "invalid_ifsc_format",
"message": "The IFSC code is invalid.",
"request_id": "req_0123456789abcdef0123456789abcdef",
"param": "ifsc"
}
}| HTTP | type | Meaning |
|---|---|---|
| 200 | — | Success |
| 204 | — | CORS preflight (OPTIONS) |
| 304 | — | Conditional GET hit (IFSC/HSN/SAC lookup only) |
| 400 | validation_error | Invalid request; inspect error.param |
| 401 | authentication_error | Missing or invalid API key |
| 403 | authorization_error | Key valid but access denied (inactive org/app) |
| 404 | not_found | Unknown route or well-formed code absent from dataset |
| 405 | method_not_allowed | Unsupported HTTP method |
| 415 | unsupported_media_type | GST requires Content-Type application/json |
| 429 | rate_limit_error | Daily quota exceeded |
| 500 | internal_error | Server error; retain request_id |
Default allowance is 1,000 requests per UTC calendar day per application + environment. A separate burst limiter (60 requests per 10 seconds) applies to the same subject. All keys and OAuth tokens of that application share both windows. Creating extra keys does not increase quota. TEST and LIVE have separate windows. This is not a billing plan and not volumetric DDoS protection.
Quota is consumed after successful authentication and authorization, before domain handling. An admitted request may count even if the response is 400, 404, 500, or 304.
Authenticated v1 lookup success for IFSC, HSN, and SAC uses private, max-age=3600 and ETag. Matching If-None-Match may return 304. Lookup 404 uses private, max-age=60. GST is private, no-store. Not every endpoint supports 304.
curl "https://mantechstudio.in/api/v1/ifsc/SBIN0000691" \
-H "Authorization: Bearer mantech_test_0123456789abcdef.example_secret" \
-H 'If-None-Match: "etag-from-previous-response"'Public APIs allow cross-origin requests with Access-Control-Allow-Origin: *. Cookie credentials are not used. CORS support is not permission to embed LIVE API keys in a public SPA. Production integrations should send keys from a trusted server. The Playground is a session tool for a key you paste; it is not a pattern for shipping secrets in frontend code.
mantech-hsn-sac-catalog-2026.08). Not a full CBIC schedule and not live government data.Webhook delivery is implemented in this repository and is not yet deployed. The only supported event type is webhook.test — an endpoint verification event, not a payment, invoice, loan, or ERP event.
unix_seconds + "." + raw_body. Header X-ManTech-Signature: t=<unix_seconds>,v1=<hex>.event.id.const crypto = require('node:crypto');
function verify(rawBody, header, secret, now = Date.now()) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const signed = parts.t + '.' + rawBody;
const expected = crypto.createHmac('sha256', secret).update(signed, 'utf8').digest('hex');
const a = Buffer.from(expected, 'utf8');
const b = Buffer.from(parts.v1, 'utf8');
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return false;
if (Math.abs(now / 1000 - Number(parts.t)) > 300) return false;
return true;
}
// secret placeholder only — never a real key
verify(rawBody, req.headers['x-mantech-signature'], 'whsec_example_not_a_real_secret');After verification, parse JSON, persist id, and return 2xx. If the same id arrives again, return 2xx without repeating work. Timestamp tolerance rejects captured old requests; event-id deduplication handles legitimate retries. Payloads are delivered to your URL and leave ManTech-controlled infrastructure.
A local TypeScript client lives at sdk/typescript as package mantech-typescript version 0.1.0. It is a local engineering package / not yet published. There is no public registry package for this client. Consume it from this repository until a publishing decision is made. OpenAPI remains the API contract.
Configure with apiKey or accessToken, plus an explicit baseUrl. Public v1 is not yet deployed, so the SDK does not default to a live host. Do not put API keys, OAuth client secrets, or access tokens in production browser JavaScript. OAuth client-credentials exchange and webhook verification are server-side Node helpers (**SERVER-SIDE ONLY**).
import { ManTech } from 'mantech-typescript';
const client = new ManTech({
apiKey: process.env.MANTECH_API_KEY,
baseUrl: process.env.MANTECH_BASE_URL,
});
const { data, requestId, rateLimit } = await client.ifsc.get('SBIN0000691');Curl, Node, and Python examples live under examples/. Python is examples-only — there is no Python SDK in this release. Future language SDKs are not scheduled.
/api/v1 is the current public API version. Breaking contract changes require a new major version. Deprecated fields or routes are documented before removal when possible. Security-critical changes may require accelerated action. No 12-month or 24-month support guarantee is published.
Legacy /api/ifsc/** exists for the website IFSC tool only. New integrations must use /api/v1/ifsc/**. Removal is not scheduled.
401 invalid_api_key — check copy/paste, revoked status, test vs live prefix, and application/organization status.429 daily_quota_exceeded — wait for Retry-After / reset, or inspect usage in the console.400 validation_error — inspect error.param.404 — verify the code exists in the dataset, or that the path is a documented /api/v1 route.500 internal_error — retain request_id and retry with backoff. Do not retry unchanged 400/401/403/404 requests in a loop.Recommended retries: 400 do not retry unchanged; 401/403 fix credentials; 404 generally do not retry unchanged lookups; 429 wait for Retry-After; 500 bounded retry with backoff. No server-side timeout SLA is published. Configure a reasonable client timeout. No availability percentage or 24/7 support commitment is claimed.
Examples in this documentation use the obvious placeholder mantech_test_0123456789abcdef.example_secret.
GST example body used in reference pages: { "amount": "1000.00", "taxRate": 18, "pricingMode": "exclusive", "supplyType": "intra_state" }