Skip to content
Security

We never see a card number.

ESDvalidator works on the order data that sits next to the payment: line items, tax, freight and commodity codes. Here is exactly what we store, what we refuse, and who processes it.

No card numbers

We never receive full card numbers. A request that contains one is rejected and nothing from its body is stored.

Encrypted everywhere

TLS 1.2 or higher in transit. AES 256 at rest. API keys are stored as a keyed hash and shown once.

Least privilege

Row level security on every table, scoped to your organization. Staff access is limited to the people who run the service.

Short retention

Request bodies are off in live. In test they expire after 7 days. Metadata is kept 13 months, then deleted.

What we store

Only what your dashboard needs.

  • Line items, amounts, tax, freightValidated in memory. In live, we keep the sale amount, merchant name and result for 13 months, never the line items.
  • Score, findings, level reachedKept 13 months for your dashboard.
  • Card brand, product, issuer countryFrom the card object you send, to find the rate.
  • BINOnly if you send it, as the first 6 digits.
  • Batch filesEach line only until its item is processed; batches and results for 30 days. A line with a card number is rejected.
  • Webhook endpointsThe URL until you delete it. The signing secret only encrypted, shown once. Events and deliveries for 30 days, with no card data.

What we never store

If a request carries a full card number, or a field named for the CVV or expiry date, we reject it.

  • Card numbers (PAN)
  • Fields named for CVV or expiry
  • Full request bodies from live keys are never stored.
Card number detection

A card number never gets past the front door

Every field is scanned for 13 to 19 digit sequences that pass the Luhn check before we parse the payload. A match returns 422 pan_detected with a pointer to the field. Nothing is logged, cached or stored.

POST /v1/validate422 pan_detected
{
  "type": "https://esdvalidator.com/errors/pan_detected",
  "title": "Request contains a card number",
  "status": 422,
  "detail": "Remove card numbers from the request. Send only the card brand, product and BIN.",
  "errors": [{ "pointer": "/metadata/note" }]
}

Fee report uploads

How the Diagnostic handles the Adyen or Stripe report you upload.

  • Card numbers stop the fileA full card number anywhere stops the read and rejects the file.
  • Buyer columns dropped on readCard, shopper and email columns never leave the parser.
  • Never written to diskWe read each file in memory. It is never saved to a disk or a bucket.
  • Summary kept, detail for 90 daysThe summary stays until your organization deletes it. Per-sale detail expires 90 days after the diagnostic runs.

Signing in

Who can reach your organization and how.

  • Email and passwordPasswords of at least 12 characters. Email confirmation is mandatory.
  • Optional two-factorAnyone can turn on an authenticator app. The owner can require it for everyone in the organization.
  • Confirmation for sensitive changesCreating a live key, revoking keys and changing members asks for a fresh authenticator code, or the password for people without two-factor. With two-factor on, test keys ask too. All of it is written to the audit log.
  • Sessions you can endA session ends after 12 hours, or after 30 days with “Keep me signed in”. Your account lists each one with its browser and city, and signs out any of them.
  • Trusted devicesSkipping the code at sign-in lasts 30 days on that browser. We keep only a hash of the device token, and sensitive changes still ask for the code.

Subprocessors

We tell customers 30 days before adding one.

CompanyPurposeLocation
VercelHosting for the site, portal and APIUnited States
SupabaseDatabase, encrypted at restUnited States
ResendTransactional emailUnited States

Report a vulnerability

Report vulnerabilities to hi@esdvalidator.com.