Adspenta

Security

Your clients' data is invisible to your other clients, and to us.

This page is written for the person at your client who has to sign off on a new tool. It covers how an agency ad management platform holding several clients' ad accounts keeps them apart. Plain English, short paragraphs, no jargon walls. If something here is not clear enough to forward, tell us and we will rewrite it.

Row-level tenant isolation Encrypted platform keys Approval-gated writes Two independent audits

What is in place, control by control

Separation

In place

One agency cannot see another, in the database itself

Every row of data belongs to exactly one tenant, meaning one agency. The rule that enforces this lives in the database rather than in application code. It is PostgreSQL row-level security, so a query that forgets to filter by tenant returns nothing instead of someone else's data.

We chose that on purpose. Application-level checks are one forgotten WHERE clause away from a leak. A database policy fails closed.

How we check it. The isolation rules are covered by the automated test suite, which runs against a real PostgreSQL database, never a stand-in, on every change. Those tests are part of the 840.

Platform keys

In place

Access tokens are encrypted, and bound to the connection they belong to

When you connect a Meta or Google ad account, the platform gives us an access token. That token is encrypted before it is stored, and the encryption is tied to the specific connection record it belongs to. A token copied out of one row cannot be decrypted and used against another.

Tokens are never written to logs, never shown in the interface, and never sent anywhere except to the platform they came from. Disconnecting an account revokes the token with the platform and deletes our copy.

Approval gating

In place

There is no code path that changes an ad account without a human approval

Executing a change requires an approval record: which proposal, which person, at which second. Without one, the execution step refuses and logs the refusal. This is not a setting you can turn off in a hurry.

Four independent locks sit in front of every write, and all of them start in the safest position: the platform is in dry run, the account has live writes off, the guardrails cap how much one change can move, and the halt button stops everything at once.

The take-back window. For five minutes after an approval, one click restores the previous value. Nothing has been sent to the platform during those five minutes.

Our own staff

In place

We cannot read your ad data, and every read we can do is logged

The operator console we use to run the service, to see whether a job failed or to help with a sign-up, has no route to campaign data inside a tenant. It sees account names, job status, error messages and billing state. It does not see spend, creatives, audiences or performance.

Where an operator can reach anything belonging to a tenant at all, the access is written to the same append-only log as everything else, with who, when and what. That log is visible to you, not only to us.

The ledger

In place

Append-only: entries are added, never edited or deleted

Every read, finding, proposal, approval, decline, take-back, execution, verification and blocked action is one line with a timestamp. Corrections are new lines that reference the old one. There is no edit button, for you or for us.

That is what makes the history worth anything: if it could be quietly tidied up, it would not be evidence.

Hosting & backups

In place

Hosted in the EU, backed up daily, restores tested

The service runs on Hetzner Online GmbH infrastructure in Finland, with Germany as the secondary region. Data stays in the EU. Backups are taken daily, encrypted, and kept off the machine that made them.

A backup you have never restored is a hope, not a backup, so restores are exercised rather than assumed.

The backup storage provider is [backup storage, to be chosen] and will be named here, and in the subprocessors list, once it is chosen.

Audits

Two rounds complete

Two independent security audits, findings published

Two rounds of review by people who do not work for us, looking at tenant isolation, token handling, the approval path and the operator console. What they found and what we changed is written up in the changelog, including the round that found something.

We publish the findings because an audit nobody can read is a logo, not a control.

Language model

In place

What we send to Anthropic, and what we do not

The chat and the drafted client updates use Anthropic's models. What is sent is a snapshot of account metrics: campaign names, budgets, spend, results, the figures you can see on the screen. The model explains them.

No personal data about your clients' customers is sent, because Adspenta never holds any: it reads aggregate ad-account reporting, not individual-level data. The model has no ability to call the ad platforms, and no route to execute anything.

Starting position

In place

Dry run first, always

Every new platform connection starts in dry run and every new account starts with live writes off. In dry run the system does the whole loop. It reads, notices, proposes and records your approval, then stops before sending anything. You get a week of proposals to judge before anything can move money.

Built in dry-run first. Live is a switch you flip, per account, on purpose.

Questions

Ask us

Procurement, DPAs and security questionnaires

Agencies whose clients ask for paperwork can have it. A Data Processing Agreement is available on request; the subprocessor list is public and dated; and if a questionnaire asks something this page does not answer, write to hello@adspenta.com and you will get a straight answer rather than a brochure. The daily loop and the four locks are described step by step, and the pricing page says what a connected account costs.

Read the rest before you decide.

The terms, the privacy policy, the subprocessor list and the deletion instructions are all short, dated, and written to be read.