GST Number Verification for WooCommerce and WordPress
Add live GSTIN validation at checkout on WooCommerce and WordPress with a lightweight API integration.
GST number verification on WooCommerce means adding a GSTIN field to checkout, validating it server-side against a live API before the order is created, and storing the confirmed legal name on the order for B2B invoicing. This is a small, self-contained plugin — a few WordPress hooks and one outbound API call — not a heavyweight extension.
Why validate a GSTIN at WooCommerce checkout
A B2B customer checking out on WooCommerce will often type their GST number into a free-text field so they can claim input tax credit against the purchase. If that field is never validated, you end up with typos, made-up numbers, and GSTINs that were valid once but are now cancelled — all of which produce a GST invoice the customer's accountant will reject. Verifying the GSTIN against live GSTN data at the point of checkout catches this before the order ships, not after a support ticket arrives.
Where the API key actually belongs
Define the key as a constant in wp-config.php, outside the web root's document tree if your
hosting allows it. This keeps it out of the database entirely, which matters because WordPress post meta
and the wp_options table are both readable by any plugin with database access, and are a
common target if the site is ever compromised.
// wp-config.php
define('GSTINAPI_KEY', 'YOUR_API_KEY');
Adding a GST number field to checkout
Hook into woocommerce_checkout_fields to add an optional field in the billing section.
Keep it optional at this layer — the server-side hook below is what actually enforces correctness for
customers who do provide one:
add_filter('woocommerce_checkout_fields', function ($fields) {
$fields['billing']['billing_gstin'] = [
'label' => __('GSTIN (for B2B invoice)', 'gstinapi-woo'),
'placeholder' => '27AAACR5055K1Z7',
'required' => false,
'class' => ['form-row-wide'],
'priority' => 35,
];
return $fields;
});
Validating server-side, not just in the browser
Client-side format checks are a nice-to-have for instant feedback, but they cannot tell you whether a
GSTIN was ever issued. The real check has to happen server-side, on
woocommerce_after_checkout_validation, where you can still block the order:
add_action('woocommerce_after_checkout_validation', function ($fields, $errors) {
$gstin = strtoupper(trim($fields['billing_gstin'] ?? ''));
if ($gstin === '') {
return; // field is optional
}
if (!preg_match('/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/', $gstin)) {
$errors->add('validation', __('That GSTIN is not correctly formatted.', 'gstinapi-woo'));
return;
}
$cache_key = 'gstinapi_' . $gstin;
$result = get_transient($cache_key);
if ($result === false) {
$response = wp_remote_get("https://gstinapi.com/api/get-taxpayer-info/{$gstin}", [
'headers' => ['X-API-Key' => GSTINAPI_KEY],
'timeout' => 10,
]);
if (is_wp_error($response)) {
$errors->add('validation', __('Could not verify GSTIN right now — please try again.', 'gstinapi-woo'));
return;
}
$code = wp_remote_retrieve_response_code($response);
$body = json_decode(wp_remote_retrieve_body($response), true);
if ($code === 404 || ($body['status'] ?? null) === 'not_found') {
$errors->add('validation', __('That GSTIN does not exist. Please double-check it.', 'gstinapi-woo'));
return;
}
if ($code !== 200) {
$errors->add('validation', __('Could not verify GSTIN right now — please try again.', 'gstinapi-woo'));
return;
}
$result = $body;
set_transient($cache_key, $result, 6 * HOUR_IN_SECONDS);
}
if (($result['status'] ?? '') !== 'Active') {
$errors->add('validation', __('This GSTIN is not currently active.', 'gstinapi-woo'));
return;
}
WC()->session->set('gstinapi_verified_' . $gstin, $result);
}, 10, 2);
Caching lookups with a transient
The transient in the snippet above (set_transient/get_transient) is the whole
caching layer, and it matters more than it looks: without it, a customer who fails checkout for an
unrelated reason (a card decline, a shipping address issue) and retries will trigger a fresh API call
each time, even though the GSTIN itself has not changed. A cache window of a few hours to a day avoids
burning extra verification credits on repeat lookups of the same number, while
still catching a GSTIN that gets cancelled between orders.
Storing the verified legal name on the order
Once validation passes, save the result as order meta on
woocommerce_checkout_update_order_meta so your invoicing template can pull the registered
legal name, not whatever the customer typed into their billing name field:
add_action('woocommerce_checkout_update_order_meta', function ($order_id) {
$gstin = strtoupper(trim($_POST['billing_gstin'] ?? ''));
if ($gstin === '') {
return;
}
$verified = WC()->session->get('gstinapi_verified_' . $gstin);
if (!$verified) {
return;
}
$order = wc_get_order($order_id);
$order->update_meta_data('_gstin', $gstin);
$order->update_meta_data('_gstin_legal_name', $verified['legalName'] ?? '');
$order->save();
});
This is what makes the whole flow useful for the B2B GST-invoice use case: your invoice plugin or a small custom template can now print the buyer's registered legal name and GSTIN exactly as they appear in GSTN records, which is what a business customer's accounts team needs to claim input tax credit on the purchase. If you sell at volume and want to check an existing customer list rather than validate one at a time, see our bulk GSTIN verification guide.
Frequently asked questions
A note on accuracy. GST rules change often. This article reflects our understanding as of 30 August 2026 and is general information, not tax or legal advice. For the authoritative position, check gst.gov.in and cbic-gst.gov.in, or speak to a qualified tax professional about your specific situation.
Check a GSTIN right now, free
Five lookups a day, no account required. Status, filing history, e-invoicing and jurisdiction.
Free GST search toolBuild it into your product
One REST call, JSON back. Get an API key and 20 free verification credits in under a minute.
Start freeMore on developer integration guides
Browse every guide in the GST API blog.