Learn / Exchange APIs

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.

EnvironmentBase URL
Paperhttps://paper-api.alpaca.markets
Livehttps://api.alpaca.markets

Endpoints are versioned under /v2.

Authentication

Two headers, no signature:

HeaderContent
APCA-API-KEY-IDAPI key ID
APCA-API-SECRET-KEYSecret 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:

LevelGrants
Read onlyView data across all API scopes
Full accessView and modify across all scopes
CustomPer-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.