Alpaca paper trading API
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs before acting on a number.
Alpaca’s paper trading uses the same API specification as live. The only differences are the base URL and the credentials.
That is unusually clean, and it cuts both ways. Migration is replacing two values. So is a mistake.
| Environment | Base URL |
|---|---|
| Paper | https://paper-api.alpaca.markets |
| Live | https://api.alpaca.markets |
Endpoints are versioned under /v2.
Authentication
Two headers, no signature:
| Header | Content |
|---|---|
APCA-API-KEY-ID | API key ID |
APCA-API-SECRET-KEY | Secret key |
curl -X GET \
-H "APCA-API-KEY-ID: {YOUR_API_KEY_ID}" \
-H "APCA-API-SECRET-KEY: {YOUR_API_SECRET_KEY}" \
https://paper-api.alpaca.markets/v2/account
/v2/account is the canonical “did my credentials work” check.
The absence of request signing is a genuine difference in difficulty, not a cosmetic one. Binance, Bybit and OKX each require a computed HMAC per request with a different pre-hash construction, and that is where most integration time goes — clock skew, parameter ordering, body serialisation. Alpaca removes the entire category.
Record the secret at generation. It is shown once and cannot be retrieved afterwards.
Key permissions
Alpaca supports scoped keys through Access Controls, set at generation:
| Level | Grants |
|---|---|
| Read only | View data across all API scopes |
| Full access | View and modify across all scopes |
| Custom | Per-scope choice of Read & Write or Read only |
Custom is the useful one — watchlists writable while trading stays read-only, for example.
OAuth is separate, with its own scopes requested in the authorization URL
(scope=account:write trading) and echoed in the token response. A read-only
OAuth integration omits the write scopes rather than requesting a read-only one.
Alpaca also requires OAuth apps to be approved before they can trade on users’
behalf.
The risk that comes with the convenience
Alpaca’s own documentation says it plainly: connect to the right domain to avoid running your paper algorithm against your live account.
Because the specification is identical, nothing about a live request looks different from a paper one except the host it went to. There is no schema error, no unsupported field, no different response shape. The code runs exactly as it did in testing.
In the Python SDK the switch is a paper=True / paper=False parameter that
sets the base URL for you, which removes the manual step where this goes wrong.
Prefer it to configuring the URL by hand.
If you are constructing requests yourself, derive the URL and the credentials from a single setting so they cannot disagree:
BASE, KEY, SECRET = (
("https://paper-api.alpaca.markets", PAPER_KEY, PAPER_SECRET)
if ENV == "paper"
else ("https://api.alpaca.markets", LIVE_KEY, LIVE_SECRET)
)
log.info("alpaca environment=%s base=%s", ENV, BASE)
The log line earns its place the first time you are unsure which one a process is running against.
What paper trading tests, and what it does not
Tests well: plumbing, authentication, order construction, error handling, your own workflow. That covers most of where mistakes actually live.
Does not test: realistic fills, slippage, partial fills, or market impact. Paper fills are optimistic. Any conclusion about execution quality drawn from paper is not evidence.
Also does not test: how you behave when the money is real. A workflow that felt comfortable in paper feels different when the number on the screen is yours. This is outside what paper can simulate and worth knowing before you conclude you are ready.
Streaming
WebSocket market data uses the same header names, e.g.
wss://stream.data.alpaca.markets/v2/test.
A note on data delay
Worth checking before you conclude anything from a strategy’s behaviour: access to the latest 15 minutes of market data requires a subscription to Alpaca’s Algo Trader Plus Plan. Without it you are working on delayed data.
This matters more than it sounds in an automated or AI-assisted setup, because delayed data looks exactly like current data. There is no flag on a bar saying it is fifteen minutes old, and nothing downstream — code or model — can infer it. If your logic is time-sensitive, the staleness has to be handled by you at the point of ingestion, not noticed later.
MCP note
Alpaca is the one venue in common use with an official MCP server
(alpacahq/alpaca-mcp-server), and it applies the same defensive default:
ALPACA_PAPER_TRADE is optional and defaults to true. A fresh install
trades paper unless you deliberately set it to false.
That is the pattern this whole article is about — make the safe environment the one you get by doing nothing.
FAQ
Do Alpaca paper and live use the same API?
Yes, the specification is identical. Switching environments is changing the base
URL from paper-api.alpaca.markets to api.alpaca.markets and swapping the
credentials, with no code changes. That is what makes migration easy and what
makes pointing at the wrong one easy.
Can I use my live API key for paper trading?
No. Paper and live have separate credentials, and a paper key does not work against the live host or vice versa. This is a safety feature — an environment mix-up produces an authentication error rather than a real order.
Can I make an Alpaca key read-only?
Yes. Generate it with Read only access, or use Custom and set the
trading scope to Read only while leaving other scopes as needed. For OAuth, omit
trading and account:write from the requested scope.
I lost my Alpaca secret key — can I retrieve it?
No. The secret is displayed once at generation and is not retrievable afterwards. Generate a new key pair and update whatever was using the old one.