Privacy Policy — Botach PD Buyback
Version 2026-10-18.2 · Effective 2026-10-18
Who we are
Botach, Inc. ("Botach", "we", "us") runs the PD Buyback portal at buyback.botach.com. When a police department retires the firearms its officers carry on duty, those officers can buy them through this portal. An officer finds the firearm the department listed for them, confirms it, enters their details, chooses or accepts the licensed firearms dealer (FFL) that will receive it, and pays by card. Botach then ships the firearm to that dealer, who completes the transfer.
This policy covers the portal only. It does not cover Botach's online store at botach.com.
Botach, Inc. · 4855 W Harmon Ave, Las Vegas, NV 89103 · United States · buyback@botach.com
Summary
- We use your information to let you buy the firearm your department listed for you, ship it to a licensed dealer, and keep the records the sale needs.
- We don't sell your information, and we don't use it for targeted advertising (ads chosen from your activity on other websites). The portal runs no advertising or analytics scripts. We do email you invitations and reminders about your department's buyback. Those emails are promotional, and you can unsubscribe at any time.
- You type your card into Authorize.net's payment form. Your card number never reaches Botach's servers.
- Officers' names, serial numbers, email addresses, phone numbers, billing addresses and IP addresses are encrypted in our database and deleted from it on the schedule under How long we keep it. If you buy, your order in Botach's online store is kept as Botach's record of the sale, and our service providers keep their own copies. What our software does not encrypt is listed under How we protect it.
Notice at collection
This section sums up what we collect from officers, why, and how long we keep it. The details follow below. We don't sell any of it or share it for advertising.
| Category (as California law names it) | What it includes | Why | Sold or shared? | How long we keep it |
|---|---|---|---|---|
| Identifiers | Name, email, phone, billing address, IP address, and a random device ID in a cookie | Find your firearm, take your order, contact you about it, verify your card, keep the portal secure | No | In the portal: deleted 30 days after the buyback closes (for a buyback that never opens or has no deadline, see How long we keep it); if you buy, until 18 months after the last recorded step on your order. The device ID cookie lasts 1 year. A coded digest of an address that unsubscribed, complained or bounced is kept for as long as Botach sends buyback email. If anyone asks for a staff sign-in link for an address that isn't a staff address, the IP address of that request stays in our audit log for 1 year. Your order in Botach's online store: kept as Botach's business and tax records for as long as the law requires |
| Customer records | The same details, and your card number, which you type into Authorize.net's form | Take your payment | No | As above. Authorize.net keeps the card details under its own rules; Botach never receives them |
| Commercial information | The firearm (model and serial number), price, tax, totals, payment, shipping and refund status, and what you accepted and when | Sell and ship the firearm, keep the record of the sale, answer card disputes | No | As for identifiers |
| Internet or other electronic network activity | Your browser type, lookup attempts (stored only as coded digests), the bot-check result, and our hosting provider's request logs | Security, fraud prevention, card-dispute evidence | No | On your claim: as for identifiers. Security logs: 1 year. Hosting request logs: 1 day |
| Geolocation (not precise) | The ZIP code you type to find a dealer | Show dealers near you | No | Not stored |
| Professional or employment-related information | Your department, and that it listed you as the officer assigned to the firearm | Confirm who may buy the firearm, and invite you | No | As for identifiers |
| Sensitive personal information | Your card number with its security code, which Authorize.net collects for us | Only to process your payment | No | Not stored by Botach |
We don't collect characteristics of protected classes, biometric information or inferences about you. We use sensitive personal information only to process your payment, one of the purposes California law allows (Cal. Code Regs. tit. 11, § 7027(m)), so there is nothing to limit. For staff accounts, see Information about Botach staff.
Where your information comes from
- From your department. The department gives Botach its trade-in list: each firearm's serial number and the officer it is assigned to, with the officer's name and, where the department has them, email address and phone number.
- From you. The serial number and last name you enter to find your firearm; your full legal name, email, phone and billing address; the FFL you choose; and your acceptance of the Terms of Sale.
- Automatically. Your IP address and browser details when you use the portal, the cookies described under Cookies, and the result of an automatic bot check.
- From our service providers. Whether your payment was approved and whether the billing address and card code matched (Authorize.net); your order number, tax, and the carrier and tracking number of the shipment (Botach's store); and whether an email to you bounced or was marked as spam (our email provider).
- Public records. FFL names, addresses, phone numbers and license numbers come from the ATF's public list of licensed dealers.
What we collect and why
The tables in this section are generated from our data inventory: the list of every database column and of the other places where the portal handles personal data. Our software checks the database part of that list every time it is built, so a column that is missing from it stops the build.
Information about officers
These are the details that identify you: your name, your firearm's serial number, your email address, phone number and billing address, and the IP address and browser you used. Before our software saves them in its own database it encrypts each one (AES-256-GCM), and the encryption keys are kept outside the database. Copies held by our service providers, such as your order in Botach's online store, the payment at Authorize.net and the emails Resend sends, are not encrypted by our software. The table also lists details you type that we use for one request and never store as you typed them: the serial number and last name on the lookup form, and the ZIP code you type to search for a dealer.
| Information | Why we use it | How long we keep it | Who processes it |
|---|---|---|---|
| The parsed spreadsheet (names, serials, emails, phones) while the import is in progress. When a mapping needs help, the AI Gateway gets each column's header and masked value shapes (letters become A/a, digits 9; never a value). A header made only of recognised header vocabulary (e.g. "Serial number") is sent in clear; everything else is masked the same way. Nothing sent is stored (encrypted) | Let staff confirm the column mapping and review issues before importing | Until the import is committed or the sheet is discarded. After 24 hours it can no longer be used, and it is deleted by the hourly scheduled purge, or sooner at the next upload, sheet view or import in any trade. Deleted data stays in Neon's point-in-time restore history for the project's restore window | Neon, Vercel, Vercel AI Gateway |
| Officer full name as given in the spreadsheet (encrypted) | Identify the officer when they claim their firearm and on the order | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
| Officer first name (encrypted) | Prefill the claim form (emails never carry the officer's name) | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
| Officer surname tokens (encrypted) | Verify the lookup (serial + last name) and prefill the claim form | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
| Officer email; the recipient of invitations and reminders (encrypted) | Send invitations, reminders and confirmations; prefill the claim form | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel, Resend |
| Officer phone (encrypted) | Prefill the claim form; support contact | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
| Firearm serial number (identifies the officer’s firearm); only the last 4 characters appear in the order confirmation email (encrypted) | Show the serial to the officer and staff; name the BigCommerce line item (packing slip, Veeqo), staff note and order metafield | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel, BigCommerce, TaxJar (via BigCommerce), Veeqo (via BigCommerce), FFL transfer webhook (via BigCommerce), Resend |
| Full legal name as entered by the officer (must match ID at the FFL) (encrypted) | Name the buyer on the order and the ATF transfer | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel, BigCommerce, TaxJar (via BigCommerce), Veeqo (via BigCommerce), FFL transfer webhook (via BigCommerce), Authorize.net |
| Email entered by the officer (kept on the claim; the officer record's email and email status are not changed); the recipient of the order confirmation and shipping notice (encrypted) | Send the order confirmation and receipts | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel, BigCommerce, TaxJar (via BigCommerce), Veeqo (via BigCommerce), FFL transfer webhook (via BigCommerce), Authorize.net, Resend |
| Phone entered by the officer (encrypted) | Contact the officer about the transfer | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel, BigCommerce, TaxJar (via BigCommerce), Veeqo (via BigCommerce), FFL transfer webhook (via BigCommerce), Authorize.net |
| Billing address entered by the officer (encrypted) | Card verification (AVS) and the BigCommerce order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel, BigCommerce, TaxJar (via BigCommerce), Veeqo (via BigCommerce), FFL transfer webhook (via BigCommerce), Authorize.net |
| IP address at lookup (chargeback evidence) (encrypted) | Evidence of who placed the order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel |
| Browser user agent at lookup (chargeback evidence) (encrypted) | Evidence of who placed the order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel |
| The rendered email (recipient address, subject and body) while it is being sent, so a retry sends exactly the same message (encrypted) | Retry a send without ever sending two different emails under one key | Cleared as soon as the email is sent, skipped or fails (minutes; about 24 hours, longer if our scheduled jobs are down) | Neon, Vercel, Resend |
| The BigCommerce order created for a claim: officer name, email, phone and billing address; the FFL ship-to; the firearm model and serial in the line item name, the staff note and the order's PD Buyback metafields; amounts and the Authorize.net transaction id | Fulfil the order (Veeqo, FFL transfer), compute and report the sales tax (TaxJar), and keep the business record of the sale | BigCommerce business record (the BigCommerce order stays when our own evidence is purged); TaxJar, Veeqo and the FFL webhook receiver keep their own copies under Botach's agreements with them | BigCommerce, TaxJar (via BigCommerce), Veeqo (via BigCommerce), FFL transfer webhook (via BigCommerce) |
| The Authorize.net transaction: officer name, billing address, phone and email, the amount, the BigCommerce order id as invoice number, and Authorize.net's own card data. The officer's IP address also reaches Authorize.net, sent by the browser through the hosted form; Authorize.net stores it with the transaction (as the customer IP) and uses it in its fraud filters (e.g. the transaction IP velocity filter) | Charge the officer, settle the payment and screen it with Authorize.net's fraud filters | Authorize.net's retention as Botach's gateway | Authorize.net |
| Serial number typed on the lookup form. Refused above 40 characters, normalised in memory, then turned into keyed digests (HMAC, under every key version) that find the firearm; the serial as typed is never stored, logged or sent past the server | Find the officer's firearm, limit attempts per serial and record failed lookups | Not stored. Only keyed digests are kept: as the per-serial attempt and lock counters in Upstash (they expire about twice their 1-hour and 1-day windows after the last attempt, at most about 2 days) and in the audit log entries of failed lookups | Vercel, Upstash, Neon |
| Last name typed on the lookup form. Refused above 80 characters, normalised and turned into keyed digests in memory, then compared with the stored surname digests of the found firearm's officer; the name and its digests are never sent to Redis, the database or the audit log | Confirm that the serial belongs to the person looking it up | Not stored: no copy and no digest is kept once the request ends | Vercel |
| ZIP code typed to search for a receiving FFL near the officer. Sent as a query parameter to the read-only FFL database to find the search centre; not digested and not logged, and never a rate-limit key (the search is limited by claim and by IP digest) | Find licensed dealers near the officer | Not stored: it lives for the one request, and the answer only echoes the centre's city, state and ZIP back to the officer's browser | Vercel, Neon |
| Resend's copy of each email we send: the recipient address, subject and body (department, model names, deadline; for orders the order number, total, FFL name and the serial's last 4 characters; for staff, trade and alert summaries). Open and click tracking stay off for the sending domain (checked before launch), so no tracking pixel and no rewritten links | Deliver PD Buy Back email | Resend keeps email data 30 days on all plans | Resend |
Search keys derived from officer information
To find a record without decrypting it, we store keyed digests (HMAC-SHA256) of serial numbers, surnames, full names and email addresses, and of the details a checkout was built from. Rate limiting on lookups uses the same kind of digest of your IP address. When an address unsubscribes, marks an email as spam or bounces, we keep a digest of it on our suppression list so we never send it reminders again, in any later buyback. The unsubscribe link in our emails carries a signed token built from a digest of your address, never the address itself. The digests are made with a secret key that is kept outside the database, so the database alone does not give anyone the original names, serial numbers or addresses.
| Information | Why we use it | How long we keep it | Who processes it |
|---|---|---|---|
| Digests of every accepted surname variant | Match a typed last name without decrypting names | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
| Digest of the officer’s whole normalised name; for a second officer with the same name and a different email, of the name plus that email | Merge one officer’s rows within a trade and keep namesakes apart | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
| Digest of the lowercased email | Match bounce/complaint webhooks and de-duplicate without decrypting | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
| Digest of the normalised serial | Look up a firearm by serial and block duplicates without decrypting | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
| Keyed digest of the details, FFL and price the BigCommerce checkout was built from (detects a stale quote; not reversible) | Rebuild the checkout only when something it depends on changed | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel |
| Keyed digest of the recipient address (officer or staff); matches Resend bounce and complaint events to the suppression list without storing the address | Honour bounces, complaints and unsubscribes | 1 year after the email (delivery evidence and opt-out history); order confirmation and shipping notice rows are kept with the order's chargeback evidence, until 18 months after the last recorded step on the order; the officer link is cleared when the officer data is purged; on invitation and reminder rows that did not bounce or complain, cleared when the officer data is purged | Neon, Vercel |
| Keyed digest of an address that unsubscribed, complained or hard-bounced (never the address) | Honour an opt-out in every later email, in every trade (CAN-SPAM 15 U.S.C. 7704(a)(4)) | Kept for as long as Botach sends PD Buy Back email, so an opt-out is never forgotten; never deleted by the purge job | Neon, Vercel |
| Lookup rate-limit counters keyed by a keyed digest of the client IP (/64 and /48 for IPv6), the random device id, the serial digest and the trade id — never a raw IP, serial or name | Block enumeration of serial numbers and surnames | Expire after about twice their window (sliding windows of 15 minutes to 1 day, so at most about 2 days) | Upstash |
| Signed token in unsubscribe links and the List-Unsubscribe header: a keyed digest of the recipient address plus the officer and trade ids, never the address | Let an officer unsubscribe with one click, without signing in | Valid indefinitely (CAN-SPAM requires at least 30 days); it carries nothing that is stored elsewhere in clear. It travels in the request URI of the unsubscribe page, its form post and the one-click endpoint, so Vercel's runtime logs record it with the request's query string for their retention: 1 hour on Hobby, 1 day on Pro, 3 days on Enterprise, 30 days with Observability Plus, longer only if a log drain is configured | Resend, Vercel |
Email delivery status
We record whether email to an officer's address bounced, was marked as spam, or whether the officer unsubscribed from reminders, so that we stop emailing that address. Our email provider reports bounces and complaints to us.
| Information | Why we use it | How long we keep it | Who processes it |
|---|---|---|---|
| Whether the officer's email is ok, bounced, complained or unsubscribed. An unsubscribe or a complaint survives an email change and is never lowered; a bounce clears only for a different address that is not itself suppressed | Stop emailing an officer whose address bounced, who complained or who unsubscribed | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
Information about Botach staff
Botach staff sign in to the staff area with emailed sign-in links or passkeys. We keep each staff member's work email and name, the label they give each passkey, the IP address and browser of their sessions, and an audit trail of what they did in the portal. We also hold the owner's email address in our hosting configuration, because every critical alert email goes to it. Our software does not encrypt any of this. When anyone asks for a staff sign-in link, the request is counted for 10 to 60 seconds under a keyed digest of its IP address, never the raw address, to limit repeated requests. The audit log records the raw IP address of such a request only when the email address asked for is not a staff address.
| Information | Why we use it | How long we keep it | Who processes it |
|---|---|---|---|
| Staff display name | Show who performed admin actions | Kept after the staff member is removed: removal deletes their invite and sessions, not the account (the portal can’t delete staff accounts yet) | Neon, Vercel |
| Staff work email | Send sign-in links and staff notifications | Kept after the staff member is removed: removal deletes their invite and sessions, not the account (the portal can’t delete staff accounts yet) | Neon, Vercel, Resend |
| Optional staff avatar URL (not collected by this app) | Display in the admin header if ever set | Kept after the staff member is removed: removal deletes their invite and sessions, not the account (the portal can’t delete staff accounts yet) | Neon, Vercel |
| IP address of the staff session | Protect staff accounts and investigate misuse | Until sign-out or the staff member's removal; an expired session (7 days after its last renewal) is deleted by the hourly scheduled purge | Neon, Vercel |
| Browser of the staff session | Protect staff accounts and investigate misuse | Until sign-out or the staff member's removal; an expired session (7 days after its last renewal) is deleted by the hourly scheduled purge | Neon, Vercel |
| Sign-in link payload (the staff email) or passkey challenge (the challenge, plus the staff account ID, name and display name when registering a passkey) | Send staff sign-in links and check passkey sign-ins | Until used; once expired (5 minutes), deleted at the next sign-in link or passkey check | Neon, Vercel, Resend |
| Passkey label chosen by staff (free text, may contain personal data) | Let staff tell their passkeys apart | Until the staff member deletes the passkey; kept after the staff member is removed (the portal can’t delete staff accounts yet) | Neon, Vercel |
| Invited staff email | Decide who may sign in and send invite and sign-in emails | Until the staff member is removed | Neon, Vercel, Resend |
| What it happened to (a staff email, a trade, claim or alert ID, or for an officer lookup a keyed digest of the looked-up serial; never raw officer PII) | Security and accountability for actions in the system | 1 year | Neon, Vercel |
| IP address of the requester: recorded raw only when a sign-in link is requested for an address not on the staff list, so it can be anyone's; for officer lookups only a keyed digest of the address, never the raw IP | Security and accountability for actions in the system | 1 year | Neon, Vercel |
| Better Auth rate-limit counters keyed by a keyed digest of the requester's IP (/64 for IPv6) and the auth path — never the raw address. It is the same keyed digest as the lookup counters, so our own Redis can link one address's sign-in and lookup counters; the key stays secret, so the address cannot be recovered. Anyone can request a sign-in link, so the address can be anyone's, not only staff | Limit sign-in link requests and other auth calls per address across every server instance | Expire with their window (10 to 60 seconds) | Upstash |
| The owner's email address, set in the deployment's configuration. Every critical alert email also goes to it, whatever the owner's notification preferences. The email log never holds it in clear: only a flag that an email went to the owner, at most a keyed digest, and the encrypted message only while it is being sent | Make sure critical alerts always reach the owner | Deployment configuration: kept while it is set; Resend keeps its copy of each email 30 days | Vercel, Resend |
Department contacts
Staff may note a contact person at the department, such as a name, phone number or email address, to reach the department about its buyback. Our software does not encrypt this note.
| Information | Why we use it | How long we keep it | Who processes it |
|---|---|---|---|
| Free-text contact at the department (may hold a person’s name, phone or email) | Reach the department about its trade | Until staff edit or clear it (the portal can’t delete departments yet) | Neon, Vercel |
Names that can appear in staff files and labels
Some free text isn't meant to hold personal data but can: the name of a spreadsheet a department sent (for example "Smith_John_P365.xlsx"), a gun-model label, or the name staff give a saved column layout. We treat it as personal data. It is not encrypted, it stays with the trade's records (saved layouts until a delete feature exists), and only a masked form of a file name ever reaches the AI service described under How we use it.
| Information | Why we use it | How long we keep it | Who processes it |
|---|---|---|---|
| Model name shown to staff and officers. Copied from the model label at import or typed by staff, so like the label it can hold a person's name; named in officer and staff emails | Show which gun model a firearm is | Life of the trade record (business record) | Neon, Vercel, Resend |
| Model label, either derived from the serial header or a model cell (only model words, tokens with a digit and manufacturer names are kept), or typed by staff. A staff-typed label, or a manufacturer name that is also a surname (e.g. Browning, Remington), can still hold a person's name | Group a trade's firearms by model and price them per model | Life of the trade record (business record) | Neon, Vercel |
| Uploaded file name, stored for staff (base name only, control and invisible characters removed). It can hold a person's name, e.g. "Smith_John_P365.xlsx". Only a masked form (every word that is not header vocabulary replaced by its letter/digit shape) reaches the AI Gateway, with the sheet's headers and masked value shapes (described under the parsed spreadsheet), when a mapping needs help | Show staff which file a sheet came from; its masked form hints the layout to the column mapper | Life of the trade record (business record) | Neon, Vercel, Vercel AI Gateway |
| Column mapping: field → column index, confidence and source, name format, the gun-model label (derived or staff-typed, so like the model label it can hold a person's name), and whether the AI assistant was used or failed. Holds the AI's answer only, never the headers or shapes the AI was sent | Record how the sheet was interpreted | Life of the trade record (business record) | Neon, Vercel |
| Template name typed by staff (free text, "Saved format" by default), so it can hold a person's name | Let staff recognise a saved column layout | Kept until a delete feature exists (the portal has no delete for them yet); templates are global and shared by every upload | Neon, Vercel |
| Saved column mapping: column indexes, the name format and the gun-model label (derived or staff-typed, so like the model label it can hold a person's name) | Reuse a column mapping when a sheet with the same headers is uploaded again | Kept until a delete feature exists (the portal has no delete for them yet); templates are global and shared by every upload | Neon, Vercel |
Security records
These records keep the portal secure: staff session tokens and sign-in link tokens (a sign-in link's token and an officer's claim session token are stored only as hashes), passkey public keys, rate-limit counters, bot-check results, staff alerts, browser security reports (the page, the rule and the blocked source only), our hosting provider's request logs and our database provider's short recovery history.
| Information | Why we use it | How long we keep it | Who processes it |
|---|---|---|---|
| Session token (secret) | Protect staff accounts and investigate misuse | Until sign-out or the staff member's removal; an expired session (7 days after its last renewal) is deleted by the hourly scheduled purge | Neon, Vercel |
| OAuth access token — unused, no OAuth providers are enabled | Protect staff accounts and investigate misuse | Not collected | Neon, Vercel |
| OAuth refresh token — unused | Protect staff accounts and investigate misuse | Not collected | Neon, Vercel |
| OAuth ID token — unused | Protect staff accounts and investigate misuse | Not collected | Neon, Vercel |
| Password hash — unused, password sign-in is disabled | Protect staff accounts and investigate misuse | Not collected | Neon, Vercel |
| Sign-in link token, stored as a SHA-256 hash (never the emailed token); for a passkey ceremony, a random challenge ID the browser holds in a signed cookie | Protect staff accounts and investigate misuse | Until used; once expired (5 minutes), deleted at the next sign-in link or passkey check | Neon, Vercel |
| Passkey public key (no secret material) | Protect staff accounts and investigate misuse | Until the staff member deletes the passkey; kept after the staff member is removed (the portal can’t delete staff accounts yet) | Neon, Vercel |
| Passkey credential ID | Protect staff accounts and investigate misuse | Until the staff member deletes the passkey; kept after the staff member is removed (the portal can’t delete staff accounts yet) | Neon, Vercel |
| Passkey signature counter (clone detection) | Protect staff accounts and investigate misuse | Until the staff member deletes the passkey; kept after the staff member is removed (the portal can’t delete staff accounts yet) | Neon, Vercel |
| SHA-256 of the officer's session cookie token (the token itself is never stored) | Recognise the officer's browser for one claim without a login | Session ends after 15 minutes idle or 2 hours; the hash stays with the claim record | Neon, Vercel |
| Alert ID | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel |
| Alert kind (lookup scanning, trade scanning, trade lockout, rate limiter unavailable, …); staff alert emails show its fixed plain-English label, never the code | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel, Resend |
| De-duplication key (trade id and time bucket; never personal data) | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel |
| open / resolved | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel |
| How many times the condition fired; stated in staff alert emails | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel, Resend |
| First occurrence; stated in staff alert emails | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel, Resend |
| Latest occurrence; stated in staff alert emails | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel, Resend |
| When staff were last emailed about it (cleared when it is resolved, so a recurrence is emailed again) | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel |
| When a staff member resolved it | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel |
| Staff account that resolved it, or the system monitor that resolved it automatically | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel |
| Counts, windows and trade ids (no personal data); staff alert emails carry only a fixed sentence built from it (fixed words, plus trade numbers and order and Authorize.net ids that pass their own checks), never the raw details | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel, Resend |
| Accept Hosted payment-form token (opens the hosted form for this order and amount; not cardholder data) | Show the same secure payment form again without opening a second one | Until the payment resolves or the token expires (15 minutes) | Neon, Vercel, Authorize.net |
| How many times staff were emailed about it | Tell staff about lookup scanning, serial lockouts or a rate-limiter outage | Until resolved, then deleted 1 year later by the hourly scheduled purge | Neon, Vercel |
| Officer claim session cookie: a random token (HttpOnly, SameSite=Lax, Secure); the database stores only its SHA-256 | Keep the officer on one firearm claim without a login | Expires after 15 minutes idle or 2 hours; deleted when the officer says the firearm is not theirs | Vercel |
| Random device id (HttpOnly, 1 year) used only as a rate-limit key | Slow down repeated lookups from one browser | 1 year | Vercel, Upstash |
| Vercel BotID challenge token sent with the lookup request (basic mode: no cookies, no third-party hosts, no iframe) | Tell humans from automated clients before a lookup runs | Not stored; only the verdict flags are kept on the claim | Vercel |
| Card number, expiry and security code are typed into Authorize.net's hosted form inside an iframe; the card data never reaches our servers (PCI DSS SAQ A) | Take the card payment without Botach handling card data | Not stored by Botach | Authorize.net |
| CSP-report rate-limit counters keyed by a keyed digest of the reporting IP — never a raw IP | Stop report floods from filling the alert table | Expire with their window (10 minutes) | Upstash |
| Browser Content Security Policy violation reports: only the page's route, the directive and the blocked resource's origin are kept (as an alert) — never the page's query string, the script sample or the user agent | Detect tampering with the payment page (PCI DSS 6.4.3 / 11.6.1) and other script injection | Alerts: until resolved, then 1 year | Vercel, Neon, Upstash |
| Delivery events Resend sends to the portal (they name the recipient address); only the status is kept in the email log and, for bounces and complaints, a keyed digest on the suppression list | Stop emailing addresses that bounce or complain | Not stored; the event body is discarded after processing | Resend, Vercel |
| Neon's point-in-time history of the app database: every row, including deleted ones, stays recoverable until the history window passes. A restore also keeps the database as it was before the restore in a backup branch (<branch>_old_<timestamp>) until Botach deletes it; the restore runbook deletes it the same day, or, where Neon does not allow that branch to be deleted, drops its data the same day | Restore the database after an accident or attack | 7 days after the change, then gone; a restore's backup branch until it, or its data, is deleted the same day | Neon |
| Vercel's platform logs of each request to the portal: time, path, status, IP address and browser. Our own log lines carry no names, serials, emails, phones or addresses | Operate and debug the service and investigate abuse | 1 day; no log drain copies them elsewhere | Vercel |
Records about trades, firearms and payments
These records run each buyback: the trade and its settings, gun models and prices, whether a firearm is available, reserved or paid, the steps of each claim, the receiving dealer's name, address and phone (public ATF data, so a sole proprietor's own name can appear), payment and order numbers, totals and tax, the result letters Authorize.net returns for the address and card-code checks (never the card details), what you accepted at checkout and when, the email log, and the state of scheduled jobs. None of them is an officer's name or contact detail. Some are linked to an officer's record and are deleted with it.
| Information | Why we use it | How long we keep it | Who processes it |
|---|---|---|---|
| Staff account ID; Whether the staff email was confirmed by a sign-in link; Staff account creation time; Staff account last update time; and 15 more | Run staff sign-in and the admin app | Life of the record | Neon, Vercel |
| Session ID; Session expiry; Session start time; Session refresh time; and 1 more | Run staff sign-in and the admin app | Until sign-out or the staff member's removal; an expired session (7 days after its last renewal) is deleted by the hourly scheduled purge | Neon, Vercel |
| OAuth token expiry — unused; OAuth scope — unused | Run staff sign-in and the admin app | Not collected | Neon, Vercel |
| Sign-in link or passkey challenge ID; Sign-in link or passkey challenge expiry; Sign-in link or passkey challenge creation time; Sign-in link or passkey challenge update time | Run staff sign-in and the admin app | Until used; once expired (5 minutes), deleted at the next sign-in link or passkey check | Neon, Vercel |
| Audit entry ID; Audit entry time; Who acted: a staff account ID, 'system', 'officer:anonymous' for an officer lookup, or 'officer:<claim ID>' for an officer's own claim; What happened; and 1 more | Security and accountability for actions in the system | 1 year | Neon, Vercel |
| Department ID; Department record creation time; Trade ID; Department the trade belongs to; and 34 more | Run a department buyback trade | Life of the trade record (business record) | Neon, Vercel |
| Department name, e.g. 'Hidalgo County SO'; named in officer emails; Human trade number (Trade #N); named in staff emails; Trade title; named in staff emails; Claim deadline (Pacific calendar day) or none; stated in officer emails (order emails included) and staff emails | Run a department buyback trade | Life of the trade record (business record) | Neon, Vercel, Resend |
| Officer ID; Trade the officer belongs to; Officer record creation time; Officer record last update time; and 10 more | Run a department buyback trade | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel |
| Claim/fulfilment status; counted in staff digests and milestones | Run a department buyback trade | Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles | Neon, Vercel, Resend |
| Template ID; Hash of the header row the template applies to; Staff account that saved the template; Template creation time; and 1 more | Reuse a column mapping when a sheet with the same headers is uploaded again | Kept until a delete feature exists (the portal has no delete for them yet); templates are global and shared by every upload | Neon, Vercel |
| Claim ID; Trade the claim belongs to; The one firearm this session is bound to; Officer record matched by the lookup; and 15 more | Run one officer's firearm claim from lookup to order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel |
| License number of the receiving FFL (public ATF data); sent to BigCommerce in the order’s ship-to address | Take and record the officer’s payment and the BigCommerce order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel, BigCommerce, TaxJar (via BigCommerce), Veeqo (via BigCommerce), FFL transfer webhook (via BigCommerce) |
| Receiving FFL's name, premises address and phone at selection time, re-verified at checkout (public ATF data). The name is the dealer's business name, else its license name, which for a sole proprietor may be the licensee's own name; the FFL's name, city and state appear in order emails | Take and record the officer’s payment and the BigCommerce order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel, BigCommerce, TaxJar (via BigCommerce), Veeqo (via BigCommerce), FFL transfer webhook (via BigCommerce), Authorize.net, Resend |
| Versions of the Terms of Sale and Privacy Policy the officer accepted with the attestation, stored as terms@<version>+privacy@<version> (chargeback evidence); When the officer accepted the terms and attestation; When BigCommerce last computed the totals; When the claim became paid; and 7 more | Take and record the officer’s payment and the BigCommerce order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel |
| Firearm subtotal from BigCommerce, in cents; Shipping charged, in cents; Sales tax computed by BigCommerce's tax provider, in cents; BigCommerce cart / checkout id; and 15 more | Take and record the officer’s payment and the BigCommerce order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel, BigCommerce |
| Total charged, in cents (must equal the Authorize.net amount to the cent); shown in the order confirmation and staff claim notifications; BigCommerce order id (also the Authorize.net invoice number); shown in order emails and staff claim notifications | Take and record the officer’s payment and the BigCommerce order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel, BigCommerce, Resend |
| When the payment-form token expires; When the first payment form opened; Authorize.net transaction id of the charge bound to this claim; When the charge was verified with Authorize.net; and 4 more | Take and record the officer’s payment and the BigCommerce order | Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later | Neon, Vercel, Authorize.net |
| Short lease that keeps two payment workers apart; Random id of the worker holding the lease | Take and record the officer’s payment and the BigCommerce order | Cleared after each step (3 minutes at most) | Neon, Vercel |
| Webhook event id; Authorize.net or BigCommerce; Provider notification id (Authorize.net) or hash and time (BigCommerce), for de-duplication; Provider event name; and 6 more | Take and record the officer’s payment and the BigCommerce order | Processed events are kept with their claim and deleted with it. Events about other Botach store transactions are deleted as soon as they are checked. A processed event that matched no claim is deleted a day after processing, but not while its unmatched charge is still unresolved. Events that fail every retry are kept for staff to review, with no automatic deletion; they hold no names or contact details, only provider ids that can be linked to an order | Neon, Vercel |
| Authorize.net transaction id of a PD Buyback charge that matched no order; Its invoice number (PDB + order id); When it was first seen; When it was last re-checked; and 1 more | Take and record the officer’s payment and the BigCommerce order | Until resolved, then with the alert (1 year) | Neon, Vercel, Authorize.net |
| Budget name; Start of the current minute; Lookups used this minute | Take and record the officer’s payment and the BigCommerce order | Overwritten every minute | Neon, Vercel |
| Job name; Lease that stops overlapping runs; Random id of the running invocation; Last start; and 4 more | Take and record the officer’s payment and the BigCommerce order | Overwritten by the next run | Neon, Vercel |
| Staff account the preferences belong to; Email on every paid claim; Daily summary email; Milestone emails (half claimed, all claimed, deadline in 3 days, closed automatically); and 4 more | Let each staff member choose which notifications they get | Kept after the staff member is removed: removal deletes their invite and sessions, not the account (the portal can’t delete staff accounts yet) | Neon, Vercel |
| Email ID; Which email it is (invitation, reminder, order confirmation, shipping notice, staff notification); Trade the email is about; Officer the email went to (cleared when the officer data is purged); and 15 more | Send each buyback email exactly once and show staff what was sent | 1 year after the email (delivery evidence and opt-out history); order confirmation and shipping notice rows are kept with the order's chargeback evidence, until 18 months after the last recorded step on the order; the officer link is cleared when the officer data is purged | Neon, Vercel |
| De-duplication key built from ids, template names and dates only, e.g. trade:<id>:officer:<id>:officer_reminder:2026-10-20; also sent to Resend as its Idempotency-Key; queued / sending / sent / delayed / delivered / failed / suppressed / bounced / complained / skipped / unknown; the delivery statuses come from Resend events and are counted in staff digests; Resend's id for the sent email (for the order confirmation, chargeback evidence) | Send each buyback email exactly once and show staff what was sent | 1 year after the email (delivery evidence and opt-out history); order confirmation and shipping notice rows are kept with the order's chargeback evidence, until 18 months after the last recorded step on the order; the officer link is cleared when the officer data is purged | Neon, Vercel, Resend |
| Short lease that keeps two senders apart | Send each buyback email exactly once and show staff what was sent | Cleared after each attempt (2 minutes at most) | Neon, Vercel |
| unsubscribed / complained / bounced (the strongest one seen is kept); Where it came from: the unsubscribe page, one-click unsubscribe, a staff email change for an officer who opted out, or a Resend event type; When Resend first reported the address undeliverable (hard bounce, complaint or suppression); order emails are never sent to such an address; First time the address was suppressed; and 1 more | Honour unsubscribes, complaints and hard bounces in every later email (CAN-SPAM 15 U.S.C. 7704(a)(4)) | Kept for as long as Botach sends PD Buy Back email, so an opt-out is never forgotten; never deleted by the purge job | Neon, Vercel |
| Single-row marker; Last check; Last check that found nothing wrong; Fingerprint of the columns seen in the last check; and 3 more | Check daily that the read-only FFL database still works, and raise critical alerts until a problem is fixed | Overwritten by the next check | Neon, Vercel |
| Fingerprint of the approved FFL table columns; Approved list of FFL table columns (names, types, nullability); Who approved it: the code baseline or a staff account ID; When it was approved | Check daily that the read-only FFL database still works, and raise critical alerts until a problem is fixed | Until a newer FFL schema is approved | Neon, Vercel |
| Carrier and tracking number of the order's shipment to the FFL, read from BigCommerce when the shipping notice is sent | Tell the officer how to follow the shipment to their FFL | Not stored by us; it appears only in the shipping notice | BigCommerce, Resend |
| Links in emails to the portal and to admin pages; they carry trade, claim or alert ids only (unsubscribe links carry the signed token instead) | Take the reader to the right page | Not stored; part of the email | Resend |
| Values worked out when an email is rendered: days left, the milestone, the digest day, whether an alert is critical, and per-trade counts of payments in the last day (no personal data) | Say what the email is about | Not stored; part of the email | Resend |
What we do not collect
- Your date of birth, driver's license or Social Security number. The FFL checks your identity and eligibility when it completes the transfer with you.
- Your card number, expiration date or card security code on Botach's systems. You type them into the payment form of Authorize.net, our payment processor, which collects them for us only to process your payment. Botach's servers never receive them.
- Your precise location. The FFL search uses only a ZIP code you type.
How we use it
- To find your firearm when you enter its serial number and last name, and to stop anyone else from guessing. We use automatic bot checks and limits on repeated attempts, and we log lookups with a coded digest, never your serial number or name as typed. These checks can refuse a lookup automatically; they decide nothing else about you.
- To hold the firearm for you while you complete your claim.
- To calculate tax and create your order in Botach's online store, and to take your card payment through Authorize.net. Authorize.net screens each card payment with its own fraud filters, which use your IP address.
- To ship the firearm to the FFL that will transfer it to you, after checking that the FFL's license is active.
- To call or email you about your order and its transfer, if we need to. We never use your phone number for marketing calls or texts, and we don't send text messages.
- To email you about this buyback: an invitation, reminders until you claim or the buyback closes (each with a link to unsubscribe), your order confirmation and, when Botach's store doesn't send one, a shipping notice. Unsubscribing stops invitations and reminders; it doesn't stop the order confirmation or shipping notice.
- To email Botach staff: sign-in links, and the notifications each staff member chooses (claims, a daily summary, milestones and alerts).
- To keep the records a card dispute or a legal obligation may need (see How long we keep it).
- To help staff import a department's spreadsheet. When our software can't match the columns by itself, it sends the sheet's column headings, the shape of the values in each column (for example "99A999999" in place of a serial number) and a masked file name to an AI service, which suggests which column holds what. A heading is sent as written only when it is made of ordinary header words such as "Serial number". Every other heading, every value and the file name are replaced by their shape, so names, serial numbers, emails and phone numbers are never sent.
- To protect the portal and its users, including alerts to Botach staff about unusual lookup activity, payment mismatches and problems with the FFL database.
We don't sell your information or use it for targeted advertising. Apart from the buyback invitations and reminders described above, we don't use it to market other products to you.
Who we share it with
- Our service providers, listed in the next section, who process it for us to run the portal.
- The receiving FFL (a third party, not our service provider). The firearm ships to the FFL you choose or accept, and that FFL completes the transfer with you under federal law. It keeps its own records, including ATF Form 4473, and has its own privacy practices. Botach's store records your email address on the shipment to the FFL, so the store's fulfilment services can see it.
- Your department. We don't send your department a list of the officers who bought their firearms.
- When the law requires it, for example under a subpoena or court order, or when the ATF inspects Botach's records.
- If Botach's business is sold or merged, the records may pass to the new owner under this policy.
We do not sell your personal information or share it for cross-context behavioral advertising.
Officers' home addresses
Your billing address is often your home address. We use it to verify your card and to record your order, and we never publish it. It goes only to the service providers that need it to complete your purchase: Botach's store (BigCommerce) and, through the store, its tax, fulfilment and FFL-webhook services, and Authorize.net.
Some laws let law-enforcement officers, judges, prosecutors and their families ask a business to stop disclosing their home address or personal phone number. One example is New Jersey's Daniel's Law (N.J.S.A. 56:8-166.1). You, or someone you authorize, can make that request by emailing buyback@botach.com with the subject "Address non-disclosure request", or by writing to us at the address under Contact us. Within 10 business days of receiving it, we stop disclosing your home address and personal phone number, and we confirm that in writing. If you have an order in progress, we contact you first, because we can't complete a card purchase without sending your billing address to our payment and store providers.
Service providers
These companies process information on Botach's behalf to run the portal. Under each name is the information it receives, generated from our data inventory. Vercel runs the portal and Neon holds its database, so they handle every record; their lists count the records in each category. Vercel, Neon and Upstash keep the portal's data in the United States, in the US East (Virginia) region.
Vercel
Vercel hosts the portal and runs its code. Every request to the portal passes through Vercel, which keeps request logs: the time, path, status, IP address and browser, and any query string in the address, including the token in an unsubscribe link. Vercel keeps these logs for 1 day, and no log drain copies them elsewhere. Vercel BotID, a Vercel service, checks lookup requests for bots. A small script, served from this site, runs in your browser and works out a challenge answer from technical details of your browser. The answer is sent with your lookup and checked by Vercel. BotID sets no cookies, loads nothing from other websites and uses no embedded frame. We use only its basic check; its optional deeper analysis, which Vercel's partner Kasada provides, is turned off.
- Information about Botach staff: 11 items
- Information about officers: 17 items
- Search keys derived from officer information: 8 items
- Email delivery status: 1 item
- Department contacts: 1 item
- Names that can appear in staff files and labels: 6 items
- Security records: 29 items
- Records about trades, firearms and payments: 234 items
Neon
Neon hosts the portal's Postgres database and encrypts stored data at rest. Officer details are encrypted by our software before they reach Neon. Neon keeps a short point-in-time history of the database so it can be restored after an accident (see How long we keep it).
- Information about Botach staff: 10 items
- Information about officers: 16 items
- Search keys derived from officer information: 7 items
- Email delivery status: 1 item
- Department contacts: 1 item
- Names that can appear in staff files and labels: 6 items
- Security records: 25 items
- Records about trades, firearms and payments: 234 items
Resend
Resend sends the portal's emails: invitations, reminders, order confirmations and shipping notices for officers, and sign-in links and notifications for staff. Each email reaches Resend with its recipient address, subject and body. For officers that is the department name, the gun model, the deadline and, for orders, the order number, the total, the dealer's name, city and state, the last 4 characters of the serial number and, in a shipping notice, the carrier and tracking number. Emails to officers do not carry your name. Resend tells us when an email bounces or is marked as spam, and keeps its own copy of each email for 30 days.
- Staff work email
- Sign-in link payload (the staff email) or passkey challenge (the challenge, plus the staff account ID, name and display name when registering a passkey)
- Invited staff email
- The owner's email address, set in the deployment's configuration. Every critical alert email also goes to it, whatever the owner's notification preferences. The email log never holds it in clear: only a flag that an email went to the owner, at most a keyed digest, and the encrypted message only while it is being sent
- Officer email; the recipient of invitations and reminders
- Firearm serial number (identifies the officer’s firearm); only the last 4 characters appear in the order confirmation email
- Email entered by the officer (kept on the claim; the officer record's email and email status are not changed); the recipient of the order confirmation and shipping notice
- The rendered email (recipient address, subject and body) while it is being sent, so a retry sends exactly the same message
- Resend's copy of each email we send: the recipient address, subject and body (department, model names, deadline; for orders the order number, total, FFL name and the serial's last 4 characters; for staff, trade and alert summaries). Open and click tracking stay off for the sending domain (checked before launch), so no tracking pixel and no rewritten links
- Signed token in unsubscribe links and the List-Unsubscribe header: a keyed digest of the recipient address plus the officer and trade ids, never the address
- Model name shown to staff and officers. Copied from the model label at import or typed by staff, so like the label it can hold a person's name; named in officer and staff emails
- Alert kind (lookup scanning, trade scanning, trade lockout, rate limiter unavailable, …); staff alert emails show its fixed plain-English label, never the code
- How many times the condition fired; stated in staff alert emails
- First occurrence; stated in staff alert emails
- Latest occurrence; stated in staff alert emails
- Counts, windows and trade ids (no personal data); staff alert emails carry only a fixed sentence built from it (fixed words, plus trade numbers and order and Authorize.net ids that pass their own checks), never the raw details
- Delivery events Resend sends to the portal (they name the recipient address); only the status is kept in the email log and, for bounces and complaints, a keyed digest on the suppression list
- Department name, e.g. 'Hidalgo County SO'; named in officer emails
- Human trade number (Trade #N); named in staff emails
- Trade title; named in staff emails
- Claim deadline (Pacific calendar day) or none; stated in officer emails (order emails included) and staff emails
- Claim/fulfilment status; counted in staff digests and milestones
- Receiving FFL's name, premises address and phone at selection time, re-verified at checkout (public ATF data). The name is the dealer's business name, else its license name, which for a sole proprietor may be the licensee's own name; the FFL's name, city and state appear in order emails
- Total charged, in cents (must equal the Authorize.net amount to the cent); shown in the order confirmation and staff claim notifications
- BigCommerce order id (also the Authorize.net invoice number); shown in order emails and staff claim notifications
- De-duplication key built from ids, template names and dates only, e.g. trade:<id>:officer:<id>:officer_reminder:2026-10-20; also sent to Resend as its Idempotency-Key
- queued / sending / sent / delayed / delivered / failed / suppressed / bounced / complained / skipped / unknown; the delivery statuses come from Resend events and are counted in staff digests
- Resend's id for the sent email (for the order confirmation, chargeback evidence)
- Carrier and tracking number of the order's shipment to the FFL, read from BigCommerce when the shipping notice is sent
- Links in emails to the portal and to admin pages; they carry trade, claim or alert ids only (unsubscribe links carry the signed token instead)
- Values worked out when an email is rendered: days left, the milestone, the digest day, whether an alert is critical, and per-trade counts of payments in the last day (no personal data)
Upstash
Upstash stores the counters that slow down repeated lookups, sign-in requests and browser security reports. Counters are keyed by keyed digests of the requester's IP address and of the serial number, by a random device id and by the trade, never by a raw IP address, serial number or name. Counters expire on their own, the longest within about two days.
- Better Auth rate-limit counters keyed by a keyed digest of the requester's IP (/64 for IPv6) and the auth path — never the raw address. It is the same keyed digest as the lookup counters, so our own Redis can link one address's sign-in and lookup counters; the key stays secret, so the address cannot be recovered. Anyone can request a sign-in link, so the address can be anyone's, not only staff
- Serial number typed on the lookup form. Refused above 40 characters, normalised in memory, then turned into keyed digests (HMAC, under every key version) that find the firearm; the serial as typed is never stored, logged or sent past the server
- Lookup rate-limit counters keyed by a keyed digest of the client IP (/64 and /48 for IPv6), the random device id, the serial digest and the trade id — never a raw IP, serial or name
- Random device id (HttpOnly, 1 year) used only as a rate-limit key
- CSP-report rate-limit counters keyed by a keyed digest of the reporting IP — never a raw IP
- Browser Content Security Policy violation reports: only the page's route, the directive and the blocked resource's origin are kept (as an alert) — never the page's query string, the script sample or the user agent
BigCommerce
BigCommerce runs Botach's online store, where your order is created. BigCommerce receives your name, email, phone and billing address, the receiving dealer's address, the firearm model and serial number (in the item name, a staff note and the order's extra data fields), the amounts and the Authorize.net transaction number. When your order ships, BigCommerce also gives us the carrier and tracking number for your shipping notice. The store passes the order on to the three services below, which work for Botach's store, not for the portal.
- Firearm serial number (identifies the officer’s firearm); only the last 4 characters appear in the order confirmation email
- Full legal name as entered by the officer (must match ID at the FFL)
- Email entered by the officer (kept on the claim; the officer record's email and email status are not changed); the recipient of the order confirmation and shipping notice
- Phone entered by the officer
- Billing address entered by the officer
- The BigCommerce order created for a claim: officer name, email, phone and billing address; the FFL ship-to; the firearm model and serial in the line item name, the staff note and the order's PD Buyback metafields; amounts and the Authorize.net transaction id
- License number of the receiving FFL (public ATF data); sent to BigCommerce in the order’s ship-to address
- Receiving FFL's name, premises address and phone at selection time, re-verified at checkout (public ATF data). The name is the dealer's business name, else its license name, which for a sole proprietor may be the licensee's own name; the FFL's name, city and state appear in order emails
- Firearm subtotal from BigCommerce, in cents
- Shipping charged, in cents
- Sales tax computed by BigCommerce's tax provider, in cents
- Total charged, in cents (must equal the Authorize.net amount to the cent); shown in the order confirmation and staff claim notifications
- BigCommerce cart / checkout id
- When the cart was deleted after payment
- When order creation was requested (guards against a duplicate order)
- BigCommerce order id (also the Authorize.net invoice number); shown in order emails and staff claim notifications
- When the Incomplete order was created
- When an unpaid Incomplete order was cancelled (after 2 hours without a charge)
- BigCommerce Transactions API record id from the purchase POST's reply (our own dedupe record, unique)
- When the PAID record was requested from BigCommerce (guards against a second record)
- When the payment was recorded in BigCommerce (the paid record)
- When the order was set to Awaiting Fulfillment with the staff note
- When the PD Buyback metafields were written to the BigCommerce order
- When the BigCommerce order was confirmed unable to ship after a reversal (on hold, refunded or cancelled)
- BigCommerce order id created or adopted for a claim
- The claim that owns the order (one order per claim)
- BigCommerce cart the order came from
- created or adopted
- When the order was recorded
- Carrier and tracking number of the order's shipment to the FFL, read from BigCommerce when the shipping notice is sent
TaxJar, through Botach's store
TaxJar (via BigCommerce) is the store's tax service: it calculates and reports the sales tax on your order. The portal never sends it anything directly.
- Firearm serial number (identifies the officer’s firearm); only the last 4 characters appear in the order confirmation email
- Full legal name as entered by the officer (must match ID at the FFL)
- Email entered by the officer (kept on the claim; the officer record's email and email status are not changed); the recipient of the order confirmation and shipping notice
- Phone entered by the officer
- Billing address entered by the officer
- The BigCommerce order created for a claim: officer name, email, phone and billing address; the FFL ship-to; the firearm model and serial in the line item name, the staff note and the order's PD Buyback metafields; amounts and the Authorize.net transaction id
- License number of the receiving FFL (public ATF data); sent to BigCommerce in the order’s ship-to address
- Receiving FFL's name, premises address and phone at selection time, re-verified at checkout (public ATF data). The name is the dealer's business name, else its license name, which for a sole proprietor may be the licensee's own name; the FFL's name, city and state appear in order emails
Veeqo, through Botach's store
Veeqo (via BigCommerce) is the system Botach uses to fulfil store orders. It receives the order from the store, including the firearm's serial number in the item name, so the right firearm is packed and shipped to the FFL.
- Firearm serial number (identifies the officer’s firearm); only the last 4 characters appear in the order confirmation email
- Full legal name as entered by the officer (must match ID at the FFL)
- Email entered by the officer (kept on the claim; the officer record's email and email status are not changed); the recipient of the order confirmation and shipping notice
- Phone entered by the officer
- Billing address entered by the officer
- The BigCommerce order created for a claim: officer name, email, phone and billing address; the FFL ship-to; the firearm model and serial in the line item name, the staff note and the order's PD Buyback metafields; amounts and the Authorize.net transaction id
- License number of the receiving FFL (public ATF data); sent to BigCommerce in the order’s ship-to address
- Receiving FFL's name, premises address and phone at selection time, re-verified at checkout (public ATF data). The name is the dealer's business name, else its license name, which for a sole proprietor may be the licensee's own name; the FFL's name, city and state appear in order emails
The FFL transfer webhook, through Botach's store
FFL transfer webhook (via BigCommerce): the store sends each firearm order, by webhook, to the receiver Botach uses for FFL orders.
- Firearm serial number (identifies the officer’s firearm); only the last 4 characters appear in the order confirmation email
- Full legal name as entered by the officer (must match ID at the FFL)
- Email entered by the officer (kept on the claim; the officer record's email and email status are not changed); the recipient of the order confirmation and shipping notice
- Phone entered by the officer
- Billing address entered by the officer
- The BigCommerce order created for a claim: officer name, email, phone and billing address; the FFL ship-to; the firearm model and serial in the line item name, the staff note and the order's PD Buyback metafields; amounts and the Authorize.net transaction id
- License number of the receiving FFL (public ATF data); sent to BigCommerce in the order’s ship-to address
- Receiving FFL's name, premises address and phone at selection time, re-verified at checkout (public ATF data). The name is the dealer's business name, else its license name, which for a sole proprietor may be the licensee's own name; the FFL's name, city and state appear in order emails
Authorize.net
Authorize.net, a wholly owned subsidiary of Visa, processes card payments. You type your card into Authorize.net's payment form inside our page, so the card number never reaches Botach's servers. Authorize.net also receives your name, billing address, email and phone, the receiving dealer's address, the amount and the order number. Your browser sends Authorize.net your IP address, which it stores with the transaction and uses in its own fraud filters. It tells us whether the payment was approved and whether the address and card code matched.
- Full legal name as entered by the officer (must match ID at the FFL)
- Email entered by the officer (kept on the claim; the officer record's email and email status are not changed); the recipient of the order confirmation and shipping notice
- Phone entered by the officer
- Billing address entered by the officer
- The Authorize.net transaction: officer name, billing address, phone and email, the amount, the BigCommerce order id as invoice number, and Authorize.net's own card data. The officer's IP address also reaches Authorize.net, sent by the browser through the hosted form; Authorize.net stores it with the transaction (as the customer IP) and uses it in its fraud filters (e.g. the transaction IP velocity filter)
- Accept Hosted payment-form token (opens the hosted form for this order and amount; not cardholder data)
- Card number, expiry and security code are typed into Authorize.net's hosted form inside an iframe; the card data never reaches our servers (PCI DSS SAQ A)
- Receiving FFL's name, premises address and phone at selection time, re-verified at checkout (public ATF data). The name is the dealer's business name, else its license name, which for a sole proprietor may be the licensee's own name; the FFL's name, city and state appear in order emails
- When the payment-form token expires
- When the first payment form opened
- Authorize.net transaction id of the charge bound to this claim
- When the charge was verified with Authorize.net
- Amount Authorize.net authorized, in cents
- Address-verification result letter from Authorize.net (chargeback evidence)
- Card-code verification result letter from Authorize.net (chargeback evidence; never the code itself)
- How many checks found the charge in an unclear state
- Authorize.net transaction id of a PD Buyback charge that matched no order
- Its invoice number (PDB + order id)
- When it was first seen
- When it was last re-checked
- When it matched a claim or proved to be no charge
Vercel AI Gateway
Vercel AI Gateway passes the staff spreadsheet-import requests described under How we use it to an AI model provider (our software currently asks for Anthropic's Claude models) and asks it to use only providers with a verified zero-data-retention agreement. Vercel AI Gateway receives only column headings made of ordinary header words, masked value shapes and masked file names. It never receives names, serial numbers, emails or phone numbers.
- The parsed spreadsheet (names, serials, emails, phones) while the import is in progress. When a mapping needs help, the AI Gateway gets each column's header and masked value shapes (letters become A/a, digits 9; never a value). A header made only of recognised header vocabulary (e.g. "Serial number") is sent in clear; everything else is masked the same way. Nothing sent is stored
- Uploaded file name, stored for staff (base name only, control and invisible characters removed). It can hold a person's name, e.g. "Smith_John_P365.xlsx". Only a masked form (every word that is not header vocabulary replaced by its letter/digit shape) reaches the AI Gateway, with the sheet's headers and masked value shapes (described under the parsed spreadsheet), when a mapping needs help
Cookies
The portal itself uses only the cookies it needs to work. There are no advertising or analytics cookies, and the bot check sets none. Staff who sign in also get a session cookie for the staff area.
Tracking across websites. Neither Botach nor Vercel collects information about your activity over time and across other websites through the portal. Because we don't track you across websites, sell your information or share it for advertising, we treat a browser's "Do Not Track" or Global Privacy Control signal the same as no signal: there is nothing for it to switch off. If that ever changes, we'll honor Global Privacy Control as a request to opt out.
| Information | Why we use it | How long we keep it | Who processes it |
|---|---|---|---|
| pdb_claim — Officer claim session cookie: a random token (HttpOnly, SameSite=Lax, Secure); the database stores only its SHA-256 | Keep the officer on one firearm claim without a login | Expires after 15 minutes idle or 2 hours; deleted when the officer says the firearm is not theirs | Vercel |
| pdb_device — Random device id (HttpOnly, 1 year) used only as a rate-limit key | Slow down repeated lookups from one browser | 1 year | Vercel, Upstash |
How long we keep it
- Officer information from your department is deleted 30 days after the buyback closes. If you bought your firearm, the records of your purchase (your claim, the firearm, your officer record, your order confirmation and shipping notice records, and the payment records) are kept until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), so we can answer a card dispute. Then they are deleted. If a buyback is set up but never opens, or has no deadline, its officer data is kept until Botach closes it, and for no more than 12 months.
- Claims that never reached payment are deleted 30 days after the buyback closes. A claim whose payment is still being settled at that point is deleted once it settles.
- Our email log records each email we send (which email, when, whether it was delivered, and a digest of the address, never the address itself) and is kept for 1 year; the rows for order confirmations and shipping notices are kept with the purchase records above. The rendered email is stored, encrypted, only while it is being sent (normally minutes; about 24 hours, longer if our scheduled jobs are down).
- Our unsubscribe list. If you unsubscribe, mark an email as spam, or an email to you bounces, we keep a digest of your address, never the address, for as long as Botach sends buyback email, so you never get reminders again. It is not deleted with your other information.
- Uploaded spreadsheets are never stored as files. Their contents are kept encrypted only while staff review an import, and are deleted when the import finishes or within about a day of upload. A spreadsheet's file name, which can contain a name, is kept with the trade's records, as are gun-model labels.
- Security and audit logs are kept for 1 year, and staff alerts for 1 year after they are resolved. They never hold officer names or serial numbers in readable form (lookups are logged with keyed digests). They do record which staff member acted, staff email addresses when staff accounts change, and the IP address of anyone who asks for a staff sign-in link with an address that isn't a staff address.
- Staff accounts are kept after a staff member is removed; removal ends their sign-in sessions.
- Your order in Botach's online store is Botach's business record of the sale and is not deleted by the portal. It is kept as Botach's business and tax records for as long as the law requires.
- Backups. After we delete information, it stays in our database provider's recovery history for up to 7 days, and then it is gone. If we ever restore the database, the provider also keeps a backup branch holding the database as it was before the restore. We delete that backup branch the same day. Where the provider doesn't allow a backup branch to be deleted, we drop its data the same day instead.
- Request logs. Our hosting provider keeps request logs (time, path, status, IP address, browser and any query string, including the token in an unsubscribe link) for 1 day. No log drain copies them elsewhere.
- Legal holds. If the law requires us to keep records, for example for a dispute or a court order, we may pause the deletion described here.
- Our other service providers keep their own copies under their own retention rules: Authorize.net's transaction records, the store's order (and the copies kept by the store's tax, fulfilment and FFL webhook services), and Resend's copy of each email (30 days).
Every hour our software checks these rules and deletes what is due. The full list, generated from our data inventory:
- Kept after the staff member is removed: removal deletes their invite and sessions, not the account (the portal can’t delete staff accounts yet)
- Staff display name; Staff work email; Optional staff avatar URL (not collected by this app)
- Until sign-out or the staff member's removal; an expired session (7 days after its last renewal) is deleted by the hourly scheduled purge
- IP address of the staff session; Browser of the staff session
- Until used; once expired (5 minutes), deleted at the next sign-in link or passkey check
- Sign-in link payload (the staff email) or passkey challenge (the challenge, plus the staff account ID, name and display name when registering a passkey)
- Until the staff member deletes the passkey; kept after the staff member is removed (the portal can’t delete staff accounts yet)
- Passkey label chosen by staff (free text, may contain personal data)
- Until the staff member is removed
- Invited staff email
- 1 year
- What it happened to (a staff email, a trade, claim or alert ID, or for an officer lookup a keyed digest of the looked-up serial; never raw officer PII); IP address of the requester: recorded raw only when a sign-in link is requested for an address not on the staff list, so it can be anyone's; for officer lookups only a keyed digest of the address, never the raw IP; Random device id (HttpOnly, 1 year) used only as a rate-limit key
- Until staff edit or clear it (the portal can’t delete departments yet)
- Free-text contact at the department (may hold a person’s name, phone or email)
- Life of the trade record (business record)
- Model name shown to staff and officers. Copied from the model label at import or typed by staff, so like the label it can hold a person's name; named in officer and staff emails; Model label, either derived from the serial header or a model cell (only model words, tokens with a digit and manufacturer names are kept), or typed by staff. A staff-typed label, or a manufacturer name that is also a surname (e.g. Browning, Remington), can still hold a person's name; Uploaded file name, stored for staff (base name only, control and invisible characters removed). It can hold a person's name, e.g. "Smith_John_P365.xlsx". Only a masked form (every word that is not header vocabulary replaced by its letter/digit shape) reaches the AI Gateway, with the sheet's headers and masked value shapes (described under the parsed spreadsheet), when a mapping needs help; Column mapping: field → column index, confidence and source, name format, the gun-model label (derived or staff-typed, so like the model label it can hold a person's name), and whether the AI assistant was used or failed. Holds the AI's answer only, never the headers or shapes the AI was sent
- Until the import is committed or the sheet is discarded. After 24 hours it can no longer be used, and it is deleted by the hourly scheduled purge, or sooner at the next upload, sheet view or import in any trade. Deleted data stays in Neon's point-in-time restore history for the project's restore window
- The parsed spreadsheet (names, serials, emails, phones) while the import is in progress. When a mapping needs help, the AI Gateway gets each column's header and masked value shapes (letters become A/a, digits 9; never a value). A header made only of recognised header vocabulary (e.g. "Serial number") is sent in clear; everything else is masked the same way. Nothing sent is stored
- Deleted by the hourly scheduled purge 30 days after the trade closes; an officer or firearm with a charged claim is kept until that claim’s 18-month evidence period ends, and one whose payment is still settling until it settles
- Officer full name as given in the spreadsheet; Officer first name; Officer surname tokens; Digests of every accepted surname variant; Digest of the officer’s whole normalised name; for a second officer with the same name and a different email, of the name plus that email; Officer email; the recipient of invitations and reminders; Digest of the lowercased email; Officer phone; Whether the officer's email is ok, bounced, complained or unsubscribed. An unsubscribe or a complaint survives an email change and is never lowered; a bounce clears only for a different address that is not itself suppressed; Firearm serial number (identifies the officer’s firearm); only the last 4 characters appear in the order confirmation email; Digest of the normalised serial
- Kept until a delete feature exists (the portal has no delete for them yet); templates are global and shared by every upload
- Template name typed by staff (free text, "Saved format" by default), so it can hold a person's name; Saved column mapping: column indexes, the name format and the gun-model label (derived or staff-typed, so like the model label it can hold a person's name)
- Charged claims: kept for card disputes until 18 months after the last recorded step on the order (such as payment, refund, shipment, order hold or a later update), then deleted by the hourly scheduled purge. Other claims: deleted by the hourly scheduled purge 30 days after the trade closes, or once their payment stops settling if that is later
- Full legal name as entered by the officer (must match ID at the FFL); Email entered by the officer (kept on the claim; the officer record's email and email status are not changed); the recipient of the order confirmation and shipping notice; Phone entered by the officer; Billing address entered by the officer; IP address at lookup (chargeback evidence); Browser user agent at lookup (chargeback evidence); Keyed digest of the details, FFL and price the BigCommerce checkout was built from (detects a stale quote; not reversible)
- 1 year after the email (delivery evidence and opt-out history); order confirmation and shipping notice rows are kept with the order's chargeback evidence, until 18 months after the last recorded step on the order; the officer link is cleared when the officer data is purged; on invitation and reminder rows that did not bounce or complain, cleared when the officer data is purged
- Keyed digest of the recipient address (officer or staff); matches Resend bounce and complaint events to the suppression list without storing the address
- Cleared as soon as the email is sent, skipped or fails (minutes; about 24 hours, longer if our scheduled jobs are down)
- The rendered email (recipient address, subject and body) while it is being sent, so a retry sends exactly the same message
- Kept for as long as Botach sends PD Buy Back email, so an opt-out is never forgotten; never deleted by the purge job
- Keyed digest of an address that unsubscribed, complained or hard-bounced (never the address)
- Expires after 15 minutes idle or 2 hours; deleted when the officer says the firearm is not theirs
- Officer claim session cookie: a random token (HttpOnly, SameSite=Lax, Secure); the database stores only its SHA-256
- Expire after about twice their window (sliding windows of 15 minutes to 1 day, so at most about 2 days)
- Lookup rate-limit counters keyed by a keyed digest of the client IP (/64 and /48 for IPv6), the random device id, the serial digest and the trade id — never a raw IP, serial or name
- Expire with their window (10 to 60 seconds)
- Better Auth rate-limit counters keyed by a keyed digest of the requester's IP (/64 for IPv6) and the auth path — never the raw address. It is the same keyed digest as the lookup counters, so our own Redis can link one address's sign-in and lookup counters; the key stays secret, so the address cannot be recovered. Anyone can request a sign-in link, so the address can be anyone's, not only staff
- Not stored; only the verdict flags are kept on the claim
- Vercel BotID challenge token sent with the lookup request (basic mode: no cookies, no third-party hosts, no iframe)
- BigCommerce business record (the BigCommerce order stays when our own evidence is purged); TaxJar, Veeqo and the FFL webhook receiver keep their own copies under Botach's agreements with them
- The BigCommerce order created for a claim: officer name, email, phone and billing address; the FFL ship-to; the firearm model and serial in the line item name, the staff note and the order's PD Buyback metafields; amounts and the Authorize.net transaction id
- Authorize.net's retention as Botach's gateway
- The Authorize.net transaction: officer name, billing address, phone and email, the amount, the BigCommerce order id as invoice number, and Authorize.net's own card data. The officer's IP address also reaches Authorize.net, sent by the browser through the hosted form; Authorize.net stores it with the transaction (as the customer IP) and uses it in its fraud filters (e.g. the transaction IP velocity filter)
- Not stored by Botach
- Card number, expiry and security code are typed into Authorize.net's hosted form inside an iframe; the card data never reaches our servers (PCI DSS SAQ A)
- Expire with their window (10 minutes)
- CSP-report rate-limit counters keyed by a keyed digest of the reporting IP — never a raw IP
- Alerts: until resolved, then 1 year
- Browser Content Security Policy violation reports: only the page's route, the directive and the blocked resource's origin are kept (as an alert) — never the page's query string, the script sample or the user agent
- Not stored. Only keyed digests are kept: as the per-serial attempt and lock counters in Upstash (they expire about twice their 1-hour and 1-day windows after the last attempt, at most about 2 days) and in the audit log entries of failed lookups
- Serial number typed on the lookup form. Refused above 40 characters, normalised in memory, then turned into keyed digests (HMAC, under every key version) that find the firearm; the serial as typed is never stored, logged or sent past the server
- Not stored: no copy and no digest is kept once the request ends
- Last name typed on the lookup form. Refused above 80 characters, normalised and turned into keyed digests in memory, then compared with the stored surname digests of the found firearm's officer; the name and its digests are never sent to Redis, the database or the audit log
- Not stored: it lives for the one request, and the answer only echoes the centre's city, state and ZIP back to the officer's browser
- ZIP code typed to search for a receiving FFL near the officer. Sent as a query parameter to the read-only FFL database to find the search centre; not digested and not logged, and never a rate-limit key (the search is limited by claim and by IP digest)
- Resend keeps email data 30 days on all plans
- Resend's copy of each email we send: the recipient address, subject and body (department, model names, deadline; for orders the order number, total, FFL name and the serial's last 4 characters; for staff, trade and alert summaries). Open and click tracking stay off for the sending domain (checked before launch), so no tracking pixel and no rewritten links
- Not stored; the event body is discarded after processing
- Delivery events Resend sends to the portal (they name the recipient address); only the status is kept in the email log and, for bounces and complaints, a keyed digest on the suppression list
- Valid indefinitely (CAN-SPAM requires at least 30 days); it carries nothing that is stored elsewhere in clear. It travels in the request URI of the unsubscribe page, its form post and the one-click endpoint, so Vercel's runtime logs record it with the request's query string for their retention: 1 hour on Hobby, 1 day on Pro, 3 days on Enterprise, 30 days with Observability Plus, longer only if a log drain is configured
- Signed token in unsubscribe links and the List-Unsubscribe header: a keyed digest of the recipient address plus the officer and trade ids, never the address
- Not stored by us; it appears only in the shipping notice
- Carrier and tracking number of the order's shipment to the FFL, read from BigCommerce when the shipping notice is sent
- Not stored; part of the email
- Links in emails to the portal and to admin pages; they carry trade, claim or alert ids only (unsubscribe links carry the signed token instead); Values worked out when an email is rendered: days left, the milestone, the digest day, whether an alert is critical, and per-trade counts of payments in the last day (no personal data)
- Deployment configuration: kept while it is set; Resend keeps its copy of each email 30 days
- The owner's email address, set in the deployment's configuration. Every critical alert email also goes to it, whatever the owner's notification preferences. The email log never holds it in clear: only a flag that an email went to the owner, at most a keyed digest, and the encrypted message only while it is being sent
- 7 days after the change, then gone; a restore's backup branch until it, or its data, is deleted the same day
- Neon's point-in-time history of the app database: every row, including deleted ones, stays recoverable until the history window passes. A restore also keeps the database as it was before the restore in a backup branch (<branch>_old_<timestamp>) until Botach deletes it; the restore runbook deletes it the same day, or, where Neon does not allow that branch to be deleted, drops its data the same day
- 1 day; no log drain copies them elsewhere
- Vercel's platform logs of each request to the portal: time, path, status, IP address and browser. Our own log lines carry no names, serials, emails, phones or addresses
How we protect it
- Officers' names, serial numbers, contact details, billing addresses and IP addresses are encrypted in our database (AES-256-GCM) with keys kept outside it. Staff names, emails and session details, the department contact note, and file names and labels staff enter are not encrypted by our software.
- Lookups compare keyed digests. They never compare stored names or serial numbers in readable form.
- The portal is served only over HTTPS with HSTS, under a strict content security policy, and runs no third-party scripts on officer pages.
- Lookups are protected by bot checks and limits on repeated attempts, and every miss gets the same answer, whatever the reason.
- Only invited Botach staff can sign in to the staff area, with emailed sign-in links or passkeys, and their actions are logged.
- Card details are entered only into Authorize.net's payment form.
No system is perfectly secure, and we can't promise that information will never be lost or misused.
Your choices and rights
Wherever you live, you can ask us to:
- tell you whether we hold information about you, what it is, where it came from, why we use it and who we share it with, and give you a copy;
- correct information that's wrong;
- delete information about you. If you ask while your department's buyback is open and before you've claimed your firearm, you won't be able to claim it through the portal.
- give you a copy of the information you gave us, in a common electronic format.
We may keep what the law lets us keep, even if you ask us to delete it: the records of a purchase until their 18-month dispute period ends, because we may need them to answer a card dispute; records we must keep by law, including firearms records; and the coded entry on our unsubscribe list that makes sure we never email you again.
We don't sell your information, use it for targeted advertising, or use it for profiling that produces legal or similarly significant effects, so there is nothing to opt out of. We won't deny you anything, charge you differently or treat you worse for using these rights. That includes Botach employees.
- How to ask. Email buyback@botach.com, or write to Botach, Inc., Attn: Privacy, at the address under Contact us. You don't need an account.
- How we confirm it's you. We'll send a code to an email address we already hold for you: the one your department gave us, or the one you used at checkout. We'll also ask for two more details we hold, such as your order number, the last 4 characters of your firearm's serial number, or your billing ZIP code. For a copy of specific information, we'll also ask you to sign a statement, under penalty of perjury, that you are the person the information is about. We won't ask for ID documents, and we use what you give us only to confirm your request, and then delete it.
- Someone acting for you. An authorized agent can make a request for you with your signed permission. We may still ask you to confirm your identity with us directly.
- When we answer. We'll confirm we received your request within 10 business days and answer within 45 days. If we need more time, we'll tell you why within those 45 days and answer within 45 more. Requests are free, at least twice a year.
- Unsubscribing. Every invitation and reminder has an unsubscribe link. Unsubscribing stops invitations and reminders sent to that address, in this buyback and any later one. It doesn't stop the order confirmation or shipping notice for a firearm you buy.
- Your home address. If a law protects your home address because of your work, see Officers' home addresses.
Appeals and state-law details
- Appeals. If we turn down your request, in whole or in part, we'll tell you why. You can appeal by replying to our answer, or by emailing buyback@botach.com with "Appeal" in the subject. We'll answer your appeal in writing within 60 days and explain our decision. If we deny it, you can complain to your state attorney general: in Texas, through the Attorney General's consumer complaint page. In California you can also contact the California Privacy Protection Agency.
- Nevada. We don't sell personal information. You can still send a request not to sell to buyback@botach.com, our designated request address.
Children
The portal is only for adult law-enforcement officers. It isn't directed to anyone under 18, and we don't knowingly collect personal information about anyone under 18. We don't sell or share anyone's personal information, so we have no actual knowledge of selling or sharing the information of anyone under 16.
Changes to this policy
When we change this policy, we publish the new version here with a new version number and its date. We review this policy at least once a year. Each time an officer accepts the Terms of Sale at checkout, we record the versions of the Terms of Sale and of this policy that were in effect.
Contact us
Email buyback@botach.com, or write to Botach, Inc., 4855 W Harmon Ave, Las Vegas, NV 89103, United States. Send privacy requests to that email address, or by post to that postal address.