This repository has been archived on 2026-03-21. You can view files and clone it, but cannot push or open issues or pull requests.
payfrit-biz/api/setup/lookupTaxRate.cfm
John Mizerek 76f089d1b9 Auto-populate tax rate from ZIP code using API Ninjas
When business info step loads with a ZIP code, automatically looks up
the combined sales tax rate and pre-fills the field. User can still
edit if needed. Field gets light green background to indicate auto-fill.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 11:52:56 -08:00

72 lines
2.8 KiB
Text

<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfheader name="Cache-Control" value="no-store">
<cfset response = { "OK": false, "taxRate": 0, "message": "" }>
<cftry>
<!--- Get ZIP code from URL or form --->
<cfset zipCode = "">
<cfif structKeyExists(url, "zip")>
<cfset zipCode = trim(url.zip)>
<cfelseif structKeyExists(form, "zip")>
<cfset zipCode = trim(form.zip)>
</cfif>
<!--- Validate ZIP code format (5 digits or 5+4) --->
<cfif NOT reFind("^\d{5}(-\d{4})?$", zipCode)>
<cfset response.message = "Invalid ZIP code format">
<cfoutput>#serializeJSON(response)#</cfoutput>
<cfabort>
</cfif>
<!--- Use just the 5-digit portion --->
<cfset zipCode = left(zipCode, 5)>
<!--- Call API Ninjas Sales Tax API --->
<cfhttp url="https://api.api-ninjas.com/v1/salestax?zip_code=#zipCode#" method="GET" timeout="10" result="httpResult">
<cfhttpparam type="header" name="X-Api-Key" value="free">
</cfhttp>
<cfif httpResult.statusCode CONTAINS "200">
<cfset apiData = deserializeJSON(httpResult.fileContent)>
<!--- API returns an array, get first result --->
<cfif isArray(apiData) AND arrayLen(apiData) GT 0>
<cfset taxData = apiData[1]>
<!--- overall_rate is decimal (e.g., 0.095 for 9.5%) --->
<cfif structKeyExists(taxData, "overall_rate")>
<cfset overallRate = val(taxData.overall_rate)>
<!--- Convert to percentage --->
<cfset response.taxRate = round(overallRate * 10000) / 100>
<cfset response.OK = true>
<cfset response.message = "Tax rate found">
<!--- Include breakdown for transparency --->
<cfif structKeyExists(taxData, "state_rate")>
<cfset response.stateRate = round(val(taxData.state_rate) * 10000) / 100>
</cfif>
<cfif structKeyExists(taxData, "county_rate")>
<cfset response.countyRate = round(val(taxData.county_rate) * 10000) / 100>
</cfif>
<cfif structKeyExists(taxData, "city_rate")>
<cfset response.cityRate = round(val(taxData.city_rate) * 10000) / 100>
</cfif>
<cfelse>
<cfset response.message = "No rate data in response">
</cfif>
<cfelse>
<cfset response.message = "No results for ZIP code">
</cfif>
<cfelse>
<cfset response.message = "API returned status: #httpResult.statusCode#">
</cfif>
<cfcatch type="any">
<cfset response.message = "Error: #cfcatch.message#">
</cfcatch>
</cftry>
<cfoutput>#serializeJSON(response)#</cfoutput>