Security
This page describes how Mapricot protects your account, your API keys, and the requests you send. For questions it doesn't answer, email support@mapricot.com.
The short version
- We don't keep what you look up. Search text, coordinates, route waypoints, and looked-up IP addresses aren't written to logs or usage records.
- We never see your card. Payments go through Stripe Checkout.
- API keys are stored only as hashes, and the full key is shown once.
- There are no passwords. You sign in with a code sent to your email.
- The servers that answer queries aren't on the public internet. They only accept signed requests from our API gateway.
Signing in
You sign in to the dashboard with an eight-digit code sent to your email address. A code expires after 10 minutes and allows five attempts.
Signing in starts a seven-day session, held in a secure, HTTP-only cookie that page scripts can't read. The dashboard refuses any change that your browser reports came from another website, so other sites can't act on your behalf. We store only hashes of session tokens, and signing out ends the session immediately.
Accounts and roles
Each person in an account is an admin or a member. Members can create and revoke API keys and see usage and billing; only admins can manage members, buy credits, and rename the account. Account changes, such as a new member or a new key, are recorded in an audit log that can't be edited.
API keys
- Each key is 256 bits of randomness. Server keys start
mapricot_sk_and browser keys startmapricot_pk_, so secret scanners can find a leaked server key. - We store a SHA-256 hash of the key, never the key itself. The full key is shown once, when you create it.
- A key is scoped to the APIs it may call,
places,routing, orip-geolocation, and can have an expiry date. - Keys can only make API requests. They can't change accounts, members, other keys, or billing.
- You can revoke a key at any time in the dashboard. To replace one, create a new key, move your apps to it, then revoke the old one. Every billed request carries a request ID in your usage export, so you can trace how a key was used.
How a request travels
- Your app sends the request over HTTPS to
api.mapricot.com, which runs on Cloudflare. - Our gateway checks the key, its scopes, and your account's limits and balance.
- The gateway signs the request and sends it through an encrypted Cloudflare Tunnel to the server that answers it.
- That server rejects anything unsigned, expired, or already seen. Each signature covers the whole request and is valid for one use within 60 seconds. If the server can't confirm a request is new, it refuses it.
- The answer returns the same way, and the gateway records the request for billing before sending you the response.
Infrastructure
Cloudflare runs the API gateway, the dashboard, account and billing records, sign-in emails, and the cache in front of map tiles. Cloudflare encrypts this data at rest.
Hetzner dedicated servers run search, routing, IP lookup, and map tiles. They hold only open map data and no customer accounts, keys, or billing records. The servers run Talos Linux, a minimal operating system with no shell or SSH, managed only through an authenticated API. They talk to each other over a private network, a firewall closes every port to the internet except the authenticated management APIs, and they reach Cloudflare through outbound-only tunnels.
All public traffic uses HTTPS.
What we store
- Account data: your email address, name, account memberships, roles, and the audit log.
- Usage records: each billed request's ID, API, key, time, and billing outcome. Usage records don't include search text, coordinates, waypoints, or IP addresses you looked up.
- Billing records: purchases, invoices, and credit balances. Card details stay with Stripe.
Operational metrics and server logs go to New Relic for monitoring. They follow the same rule: no keys, search text, coordinates, request bodies, or looked-up IP addresses.
Payments
Credits are bought through Stripe Checkout, so card details go straight to Stripe and never reach Mapricot. We add credits only after a signed Stripe webhook arrives and the payment is confirmed directly with Stripe. A missed webhook is caught by a scheduled check, and a payment can never be credited twice.
How we build and deploy
- Production deploys only from each repository's
mainbranch, through GitHub Actions. - Production secrets live in protected GitHub environments that only
maincan use. Our repositories contain no secrets. - Container images are pinned by digest, so we know exactly what runs.
- Data releases are checksummed and stored in R2 with an object lock, so a published release can't be overwritten or deleted. Each release is checked before it goes live, and the previous release stays ready for rollback.
Service providers
| Provider | What it does for Mapricot |
|---|---|
| Cloudflare | API gateway, dashboard, account and billing data, sign-in email, map tile caching, data release storage |
| Hetzner | Dedicated servers for search, routing, IP lookup, and map tiles |
| Stripe | Payments, tax, and invoices |
| New Relic | Operational monitoring |
Questions
Do you see my users' searches or locations?
Only while answering the request. Search text, coordinates, waypoints, and looked-up IP addresses aren't written to logs or usage records.
What should I do if an API key leaks?
Rotate or revoke it in the dashboard. Rotation replaces the key immediately. Use request IDs in your usage export to review what it was used for.
Should I put an API key in a web page?
Anyone who opens the page can read a key in it. If you call Mapricot from a browser, use a separate key scoped only to the APIs that page needs, and keep keys with wider access on your servers.
How do I report a vulnerability?
Email support@mapricot.com with "Security" in the subject line. Include enough detail for us to reproduce the issue. Please don't access other people's data or disrupt the service while testing.