Some Parse APIs are built from sites that require login. These APIs have login endpoints that create sessions and protected endpoints that reuse the authenticated state.
Authenticated APIs can only be created through the Parse dashboard — not via the API or MCP. Free accounts cannot create authenticated APIs, and each account is limited to 1 authenticated session per site.
Each endpoint in an authenticated API has a session tag:
| Tag | Meaning |
|---|
initiates_session: true | Login endpoint. Returns session_id + encryption_key in the response. |
depends_on_session: "login" | Protected endpoint. Requires session_id + encryption_key from a prior login call. |
| (neither) | Public endpoint. Works without any session, even on APIs that have other auth-gated endpoints. |
Step 1: Call the login endpoint
curl -X POST https://api.parse.bot/scraper/{scraper_id}/login \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"username": "user@example.com", "password": "s3cret"}'
The response includes your data plus two session values:
{
"data": { "logged_in": true, "display_name": "Jane" },
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"encryption_key": "gAAAAABk..."
}
Store both session_id and encryption_key — you need them for every protected endpoint call. Parse does not store the encryption key.
Step 2: Call protected endpoints
Pass the session credentials via headers (preferred) or request body:
# Option A: Headers (recommended)
curl -X POST https://api.parse.bot/scraper/{scraper_id}/get_inbox \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-Session-ID: 550e8400-e29b-41d4-a716-446655440000" \
-H "X-Encryption-Key: gAAAAABk..." \
-H "Content-Type: application/json" \
-d '{"folder": "inbox", "limit": 10}'
# Option B: Body params
curl -X POST https://api.parse.bot/scraper/{scraper_id}/get_inbox \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"session_id": "550e8400-e29b-...",
"encryption_key": "gAAAAABk...",
"folder": "inbox",
"limit": 10
}'
The session state is automatically updated after each call — you don’t need to track cookies or tokens yourself.
Full example
import httpx
API_KEY = "your-api-key"
BASE = "https://api.parse.bot"
HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
scraper_id = "scraper-456"
with httpx.Client(headers=HEADERS, timeout=60) as client:
# 1. Login
resp = client.post(f"{BASE}/scraper/{scraper_id}/login", json={
"username": "user@example.com",
"password": "s3cret",
})
login = resp.json()
session_id = login["session_id"]
encryption_key = login["encryption_key"]
# 2. Call a protected endpoint
resp = client.post(
f"{BASE}/scraper/{scraper_id}/get_inbox",
headers={
**HEADERS,
"X-Session-ID": session_id,
"X-Encryption-Key": encryption_key,
},
json={"folder": "inbox", "limit": 10},
)
print(resp.json())
Session details
- One session per user per scraper: Logging in again with the same user upserts the existing session.
- Proxy binding: The proxy IP used during login is reused for all protected endpoints to prevent session invalidation from IP changes.
- Session updates are transparent: After each protected call, the session state is re-encrypted and saved automatically.
- Rate limiting: Login endpoints enforce a rate limit of 3 login attempts per hour per scraper.
Error responses
| Code | Detail | When |
|---|
| 400 | This endpoint requires session_id and encryption_key. Call the login endpoint first. | Protected endpoint called without session |
| 400 | Invalid session or encryption key | Wrong encryption key or corrupted session |
| 404 | Session not found | Invalid session_id or session belongs to a different scraper |
| 403 | Auth session limit reached | You’ve hit your per-site session cap |
Security
- Fernet session encryption: Session state is encrypted with your
encryption_key before storage. Parse stores only ciphertext — without your key, the data is unreadable.
- HMAC replay protection: Serialized session blobs are signed with a 30-minute TTL.
- No plaintext credential storage: Credentials provided during API creation are encrypted end-to-end and never stored in plaintext.