Addepar API for Wealth Management Agents
Addepar has no read-only key tier, so a key carries its user's permissions. If you want an agent that can only read portfolios, you have to build that constraint yourself.
Everything else in this series is a design discussion. This one is a compliance discussion that happens to involve an API.
Addepar holds portfolio data for wealth management firms: what clients own, what it is worth, how it has performed. In terms of sensitivity that sits alongside medical records. It is also regulated data, subject to books-and-records obligations, and your firm has told clients in writing how it is handled.
So the question is not "can an agent use this API." It is "can you show a regulator exactly what the agent read, prove it could not write, and demonstrate it only ever saw the clients it was supposed to see." All three of those are answerable. They just have to be designed in, because the API will not do it for you.
There is no read-only key, and that is the central fact
Many APIs let you mint a credential that physically cannot write. GitLab has read_api. Addepar does not have an equivalent tier: a key inherits the permissions of the user it belongs to.
Two consequences. First, create the key under a user whose own permissions are as narrow as the job requires, rather than under an administrator because that was the account you happened to be logged into. The key is a copy of that person's reach, and an admin's key is an admin's key no matter how carefully your code behaves.
Second, "read-only" has to be enforced one layer up, at the allowlist. An agent that has never been given a write method cannot call one, whatever it reasons itself into wanting, and whatever a prompt injected into a document it reads tells it to do. That is a structural guarantee rather than an instruction, and structural guarantees are the only kind you can describe to a compliance officer without hedging.
The Addepar-Firm header, and the mistake it enables
Requests go to https://api.addepar.com/v1 with basic auth using your key and secret, plus an Addepar-Firm header carrying the firm ID. Miss it and the request fails, which is fine because it fails immediately and visibly.
The dangerous case is getting it wrong rather than missing it. If your organisation spans multiple firm IDs and the agent sends the wrong one, you do not get an error. You get data. Just somebody else's.
In a regulated context, showing one firm's client holdings to another firm's adviser is a reportable incident, not a bug to fix next sprint. So the firm ID is configuration, pinned once, never a parameter a model can influence and never something assembled from context at call time. If you genuinely serve multiple firms, use a separate connection per firm, with its own key and its own allowlist, so the wrong combination is not expressible.
Setting it up
npx swytchcode
swy login
swy init --mode=sandbox
swy get addepar
swy auth connect addepar # key + secret, stored outside the project
swy auth status
swy discover "get portfolio holdings" --project addepar
swy discover "run a portfolio query" --project addepar
swy list methods addepar
swy info <canonical_id>
swy add method <canonical_id> # reads only. Nothing else. Ever.This is the shortest allowlist in the series and it should stay that way. Portfolio and position reads, the query endpoints your reporting needs, and nothing that creates, modifies or deletes a holding, a transaction or an entity.
If someone asks for write access, the answer is to build the write as a reviewed workflow where the agent prepares and a licensed human commits. Position data feeds client reporting and performance figures; an agent editing it directly is a problem no amount of model quality fixes, because the issue is accountability rather than accuracy.
Credentials sit in a local encrypted store outside your project and are injected when a call executes, so the key never enters the model's context and cannot be echoed back in a response. See the authentication docs. For firms with egress restrictions, it matters that the kernel runs on your own infrastructure and calls Addepar directly, with no vendor proxy in the path holding client data. The reasoning behind that preference is in self-hosted versus SaaS API integration for AI agents.
Policy, when the allowlist is already read-only
You still want rules, for two reasons: to make the intent explicit in a file a reviewer can read, and to catch the day somebody adds a method without thinking it through.
{
"id": "addepar-is-read-only",
"target": ["addepar.*"],
"when": { "field": "method", "operator": "in", "value": ["POST", "PUT", "PATCH", "DELETE"] },
"action": {
"type": "DENY",
"message": "Addepar access is read-only by firm policy"
}
}A deny rather than an approval gate, because there is no circumstance where you want to be asked whether the agent may modify a client portfolio at eleven at night. Check the operators and matching available in the policy reference and shape the rule to your method IDs. The important property is that it lives in version control: when an examiner asks who decided the agent could not write, the answer is a commit with a reviewer's name on it. See policy-as-code for AI agents and API access control for AI agents.
The audit trail is the deliverable
In most integrations the audit log is a debugging aid. Here it is the artifact that makes the whole thing defensible. swy audit network records every call with its arguments, timing and response; swy audit policy records what a rule stopped and why.
That turns "which client records did your AI access in March" from an uncomfortable silence into a query. Set up retention to match your books-and-records obligations rather than defaults, and treat the log as regulated data itself, because it contains the identifiers of everything that was read. Practical detail in how to log every API call an AI agent makes and API compliance for AI agent integrations.
One more thing worth deciding deliberately: which model, hosted where, under what data agreement. Portfolio data in a prompt is a data transfer. That decision belongs in your vendor assessment, and the security checklist before connecting any AI assistant to company data is a reasonable place to start the conversation with your risk team.
Using it from Claude
An adviser asking "what is this household's exposure to emerging markets" and getting an answer in seconds is the clearest value here. Through MCP in Claude Desktop that works, and with a read-only allowlist plus the deny rule the session cannot alter a single position. Setup is in the MCP setup guide, the reference in the MCP docs, and skills.md gives a coding agent the setup commands.
Do confirm with your compliance team which client data may appear in a desktop AI session before rolling that out to advisers. The technical controls are the easy half.
What you can build
- Client review prep. Before a meeting, read the household's holdings, performance and allocation and draft the discussion points. The adviser reviews and edits. Saves an hour per meeting and touches nothing.
- Drift detection across the book. Read allocations against targets and surface the accounts that have drifted past tolerance. Rebalancing stays human; finding what needs rebalancing does not.
- Concentration and exposure questions. Answer "how exposed are we to this sector across all clients" without building a report first. The sort of question that gets asked when news breaks and an answer is needed within the hour.
- Reporting-pack drafting. Turn quarterly figures into readable commentary for the client pack, with a human reviewing every number before anything is sent. Note that performance commentary may itself be a regulated communication, so route it through the same review as anything else client-facing.
FAQ
Can I make the agent genuinely read-only?
Not at the key level, since Addepar keys inherit their user's permissions. You get there by creating the key under a narrowly permissioned user, allowlisting only read methods, and denying write verbs in policy. Three layers, each independently sufficient, which is roughly the standard you want in a regulated firm.
What is the actual risk of the Addepar-Firm header?
Sending a valid firm ID that is not the one you meant returns real data for the wrong firm, with no error to alert you. Pin it in configuration and use separate connections per firm so the mistake cannot be made.
Will our compliance team accept this?
They will ask what it can do, how you know, and what the record is. A fixed allowlist, policy rules in version control, and a complete call-level audit log answer all three in writing, which is considerably better than assurances about how the system has been prompted.
What about the accounting side of the business?
Different data, different risks, and periods that close. The FreeAgent guide covers the lock-check pattern that keeps an agent out of a filed period.
Related reading
More content
SendGrid API for AI Agents
One boolean in the SendGrid payload mails people who unsubscribed. bypass_list_management is the field your agent must never be able to set.
FreeAgent API for Accounting Agents
FreeAgent lets you read accounting period locks before you write. An agent that skips that check will eventually post an entry into a period someone has already filed.
GitLab AI API and CI Agents
A personal access token gives your agent your permissions across every project you can see. A project access token gives it one project. That choice is the whole security model.
