Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: PropRaven Webhooks API
version: 1.2.1
description: 'National property intelligence API: US parcels with ownership, valuation, permit, deed, risk and market data.
**Base URL.** `https://propraven.com/api/v1` (every path below starts with `/api/v1`; `https://api.propraven.com/api/v1` serves the same API). The REST API is for server-side use: it sends no CORS headers, and API keys are secret.
**Authentication.** `Authorization: Bearer pz_…`. Create a key in the dashboard. A few endpoints are key-optional (marked with an empty security requirement); anonymous calls to them are limited to 100 a day and 60 a minute per IP. The Free plan includes 1,000 API calls a month (60 a minute, 1,000 a day); `GET /api/v1/account/usage` reports your plan, period usage and limits.
**Numbers.** Since API 1.2.0, every field this spec types as `number` or `integer` is a JSON number. (Before 1.2.0, values read from Postgres `numeric` and `bigint` columns, such as `total_assessed_value`, were sent as strings like "19388200.00".) Identifiers stay strings: `parcel_id`, `apn`, `county_fips`, `state_fips`, `zip`.
**Errors.** Every error is an RFC 7807 problem (`application/problem+json`, schema `Problem`) with a stable `code`. Bad parameters are a 400 `invalid_parameter` naming each one in `errors`; an unknown endpoint is a 404 `not_found`; an unsupported method is a 405 with an `Allow` header; a query that runs out of time is a 504 `query_timeout` with `Retry-After`. Error bodies never contain database text. Paid endpoints answer an unpaid call with an x402 `402 Payment Required` envelope (`x402Version`, `accepts`).
**Pagination.** List endpoints take `limit` and `offset` and return `{data, total, limit, offset}`; request the next page with `offset + limit` until a page is shorter than `limit` or `offset` reaches `total`. `GET /api/v1/search/full` uses a keyset cursor: pass the previous page''s `nextCursor` as `after` until `nextCursor` is null.
**Rate limits.** Burst and daily windows by plan: Free 60 a minute / 1,000 a day; Developer 3,000 a minute / 100,000 a day; Team 12,000 a minute / 1,000,000 a day; key-optional endpoints called without a key, 60 a minute / 100 a day per IP. Authenticated responses carry `X-RateLimit-Limit` / `-Remaining` / `-Reset` (Unix seconds), all describing the window that will refuse you first. Every 429 and every 503 carries `Retry-After` (seconds): wait at least that long, then retry with backoff. A **429** means your plan''s window is used up (`rate_limit_exceeded`); or the key is cooling down for up to 15 minutes because its request rate spiked far above its own recent baseline (`key_cooldown`; it is not banned or revoked, and your other keys are unaffected); or one address failed authentication more than 60 times in a minute (`auth_failures_exceeded`). A **503** means PropRaven is briefly shedding load to protect the service (`load_shed`; calls without a key first, paid plans last) or the rate limiter is briefly unavailable. The MCP endpoint (`/mcp`) answers the same cases with the same status and `Retry-After`, plus a JSON-RPC error with code -32003.
**SDKs.** Official clients generated from this spec: `@propraven/sdk` (npm), `propraven` (PyPI) and `github.com/jdw2111/propraven-go`. Each retries 429/503/504 with backoff, raises typed errors on the `Problem` shape, paginates, and verifies webhook signatures. The `x-sdk-group`, `x-sdk-method` and `x-sdk-pagination` extensions name each operation in the SDKs.'
contact:
name: PropRaven Support
url: https://propraven.com/docs
email: support@propraven.com
license:
name: Commercial
url: https://propraven.com/terms#data-license
servers:
- url: https://propraven.com
description: Production. Every path starts with /api/v1. (https://api.propraven.com serves the same API.)
security:
- bearerAuth: []
tags:
- name: Webhooks
description: Webhook subscriptions and delivery history. Manage which events PropRaven pushes to your endpoints.
paths:
/api/v1/webhooks:
get:
operationId: listWebhooks
summary: List webhook endpoints
description: Returns every webhook endpoint of the calling account (active and disabled), plus the quota of the caller's API tier.
tags:
- Webhooks
security:
- bearerAuth: []
responses:
'200':
description: Webhook endpoints returned.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
type: object
required:
- webhooks
- quota
- tier
properties:
webhooks:
type: array
items:
$ref: '#/components/schemas/Webhook'
quota:
$ref: '#/components/schemas/WebhookQuota'
tier:
type: string
enum:
- free
- starter
- pro
- scale
- api_100k
description: 'The API tier key that sets this account''s webhook quota, not the plan name on /pricing: `pro` = Developer, `scale` = Team, `free` = Free; `starter` and `api_100k` are legacy API plans.'
additionalProperties: false
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/RateLimitExceeded'
'405':
$ref: '#/components/responses/MethodNotAllowed'
'500':
$ref: '#/components/responses/InternalError'
x-sdk-group: webhooks
x-sdk-method: list
post:
operationId: createWebhook
summary: Create a webhook endpoint
description: Creates a new webhook subscription. The returned `secret` is shown ONCE — store it server-side and use it to verify every incoming delivery via the `X-PropRaven-Signature` header (HMAC-SHA256 over `.`). Reject deliveries where `|now - t| > 5min`. Every request field is validated before anything is created; `filter_value.parcel_ids` entries are stored as canonical ids (`state_fips:county_fips:parcel_id`). Only active endpoints count toward your quota.
tags:
- Webhooks
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WebhookCreate'
responses:
'201':
description: Webhook created. Response includes the one-time secret.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
$ref: '#/components/schemas/WebhookCreated'
'400':
description: Invalid url, event_types, filter_kind, or filter_value.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'422':
description: 'One or more parcel ids do not name exactly one parcel (`code: parcel_identity_unresolved`). `issues[]` lists each input with `code` (parcel_id_ambiguous | parcel_not_found | invalid_parcel_identifier) and, when ambiguous, the candidate canonical ids. Nothing was created.'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'402':
description: Tier quota reached or feature gated. Body includes upgrade guidance.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'501':
description: 'Reserved for an event type the API accepts before PropRaven emits it. No current event type returns 501: All three event types are live: create accepts each of them and PropRaven emits each of them.'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/RateLimitExceeded'
'405':
$ref: '#/components/responses/MethodNotAllowed'
'500':
$ref: '#/components/responses/InternalError'
x-sdk-group: webhooks
x-sdk-method: create
/api/v1/webhooks/{id}:
get:
operationId: getWebhook
summary: Get a single webhook endpoint
description: Returns one endpoint as the same snake_case record GET /webhooks lists (the `Webhook` schema). The secret is never returned.
tags:
- Webhooks
security:
- bearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
description: Webhook endpoint ID.
responses:
'200':
description: Webhook endpoint returned.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
$ref: '#/components/schemas/Webhook'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
'400':
$ref: '#/components/responses/BadRequest'
'405':
$ref: '#/components/responses/MethodNotAllowed'
'500':
$ref: '#/components/responses/InternalError'
x-sdk-group: webhooks
x-sdk-method: get
delete:
operationId: deleteWebhook
summary: Soft-disable a webhook endpoint
description: 'Soft disable, not a delete: sets `is_active: false`, `disabled_reason: "user"` and `disabled_at`. The endpoint stays in GET /webhooks with its delivery history (readable via the deliveries route). Nothing more is sent to it, including deliveries already queued. There is no hard delete and no re-enable or update operation; create a new endpoint instead. A disabled endpoint does not count toward the quota.'
tags:
- Webhooks
security:
- bearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
description: Webhook endpoint ID.
responses:
'200':
description: Webhook disabled. `deleted` echoes the endpoint id.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
type: object
properties:
deleted:
type: string
format: uuid
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
'400':
$ref: '#/components/responses/BadRequest'
'405':
$ref: '#/components/responses/MethodNotAllowed'
'500':
$ref: '#/components/responses/InternalError'
x-sdk-group: webhooks
x-sdk-method: delete
/api/v1/webhooks/{id}/deliveries:
get:
operationId: listWebhookDeliveries
summary: Recent delivery attempts for a webhook
description: Returns the last 100 delivery attempts for an endpoint — useful for debugging signature mismatches, retry visibility, and dead-letter inspection.
tags:
- Webhooks
security:
- bearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
description: Webhook endpoint ID.
responses:
'200':
description: Recent deliveries returned (max 100, newest first).
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
type: object
properties:
deliveries:
type: array
items:
$ref: '#/components/schemas/WebhookDelivery'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
'400':
$ref: '#/components/responses/BadRequest'
'405':
$ref: '#/components/responses/MethodNotAllowed'
'500':
$ref: '#/components/responses/InternalError'
x-sdk-group: webhooks
x-sdk-method: deliveries
/api/v1/webhooks/{id}/deliveries/{deliveryId}/retry:
post:
operationId: retryWebhookDelivery
tags:
- Webhooks
security:
- bearerAuth: []
summary: Re-queue a failed webhook delivery
description: Moves a `pending`, `failed` or `dead_lettered` delivery back to `pending` for immediate redelivery. A delivered one is a 409.
parameters:
- name: id
in: path
required: true
description: Webhook endpoint id.
schema:
type: string
example: 9b2f6c1e-0000-4000-8000-000000000000
- name: deliveryId
in: path
required: true
description: Delivery id.
schema:
type: string
example: 4c1d2e3f-0000-4000-8000-000000000000
responses:
'200':
description: The re-queued delivery.
content:
application/json:
schema:
type: object
required:
- id
- status
- next_attempt_at
- attempts
additionalProperties: false
properties:
id:
type: string
status:
type: string
enum:
- pending
next_attempt_at:
type:
- string
- 'null'
format: date-time
attempts:
type: integer
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
'409':
description: The delivery is not retryable.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'405':
$ref: '#/components/responses/MethodNotAllowed'
'429':
$ref: '#/components/responses/RateLimitExceeded'
'500':
$ref: '#/components/responses/InternalError'
x-sdk-group: webhooks
x-sdk-method: retryDelivery
components:
headers:
X-RateLimit-Reset:
description: Unix timestamp (seconds) when the window described by X-RateLimit-Limit resets.
schema:
type: integer
example: 1711670400
Retry-After:
description: Seconds to wait before retrying.
schema:
type: integer
example: 5
X-RateLimit-Remaining:
description: Calls left in the window described by X-RateLimit-Limit.
schema:
type: integer
example: 997
X-Request-Id:
description: Support handle for this request; equals the problem body's `request_id`. Sent on every error response, including 401.
schema:
type: string
X-RateLimit-Limit:
description: Size of the rate-limit window that will refuse you first — the per-minute burst window or the per-day window, whichever has fewer calls left. Limit, Remaining and Reset always describe that same window. Sent on every authenticated response (and on anonymous responses of key-optional endpoints).
schema:
type: integer
example: 1000
schemas:
Webhook:
type: object
properties:
id:
type: string
format: uuid
url:
type: string
format: uri
description: Customer endpoint. Must be https://.
secret_prefix:
type: string
description: First 14 characters of the secret (`whsec_` + 8 hex). Identifies the endpoint; the full secret is shown only in the create response.
event_types:
type: array
items:
type: string
enum:
- parcel.sold
- parcel.permit_filed
- parcel.owner_changed
filter_kind:
type: string
enum:
- parcel_ids
- state_fips
- county_fips
filter_value:
$ref: '#/components/schemas/WebhookFilter'
description:
type:
- string
- 'null'
maxLength: 200
is_active:
type: boolean
description: false after DELETE (a soft disable).
created_at:
type: string
format: date-time
disabled_at:
type:
- string
- 'null'
format: date-time
disabled_reason:
type:
- string
- 'null'
description: '`user` when disabled with DELETE; null while active.'
deliveries_attempted:
type: integer
deliveries_succeeded:
type: integer
last_delivery_at:
type:
- string
- 'null'
format: date-time
last_success_at:
type:
- string
- 'null'
format: date-time
identity_status:
type: string
enum:
- canonical
- legacy_bare_parcel_ids
description: 'parcel_ids endpoints only. `legacy_bare_parcel_ids`: the endpoint was created before 2026-09-22 with bare parcel numbers, and those that do not name exactly one parcel are not matched; recreate it with canonical ids.'
description: One webhook endpoint, as returned by GET /webhooks (each item) and GET /webhooks/{id}.
WebhookDelivery:
type: object
properties:
id:
type: string
format: uuid
description: Delivery id; sent as the `X-PropRaven-Delivery-Id` header on every attempt.
event_id:
type: string
description: Deterministic event identifier — sha256(source || pk || event_type). Idempotent re-deliveries share this.
event_type:
type: string
enum:
- parcel.sold
- parcel.permit_filed
- parcel.owner_changed
event_occurred_at:
type: string
format: date-time
status:
type: string
enum:
- pending
- in_flight
- delivered
- dead_lettered
- failed
description: '`pending` = queued or waiting for its next retry (`next_attempt_at`); `in_flight` = being sent, or the outcome of a send is unknown (network error or timeout) and it is held for reconciliation, not retried automatically; `delivered` = your endpoint answered 2xx; `dead_lettered` = all 8 attempts got non-2xx, or the send was refused before dispatch (re-queue with the retry route); `failed` = legacy value the current dispatcher never sets (still accepted by the retry route).'
attempts:
type: integer
description: Attempts made so far (at most 8).
last_attempt_at:
type:
- string
- 'null'
format: date-time
next_attempt_at:
type:
- string
- 'null'
format: date-time
last_response_status:
type:
- integer
- 'null'
description: HTTP status your endpoint returned on the last attempt; null when no status came back.
last_response_body:
type:
- string
- 'null'
description: 'Never your endpoint''s body: after any attempt that got an HTTP status back it is the fixed text `[redacted: response body not persisted]`; null before the first such attempt.'
last_error:
type:
- string
- 'null'
description: Why the last send did not complete (for example `Delivery outcome unknown; reconciliation required`); null otherwise.
dead_lettered_at:
type:
- string
- 'null'
format: date-time
created_at:
type: string
format: date-time
WebhookCreate:
type: object
required:
- url
- event_types
- filter_kind
- filter_value
properties:
url:
type: string
format: uri
description: Customer endpoint. https:// only.
event_types:
type: array
items:
type: string
enum:
- parcel.sold
- parcel.permit_filed
- parcel.owner_changed
minItems: 1
description: 'Event types to subscribe to. All three event types are live: create accepts each of them and PropRaven emits each of them.'
filter_kind:
type: string
enum:
- parcel_ids
- state_fips
- county_fips
filter_value:
$ref: '#/components/schemas/WebhookFilter'
description:
type:
- string
- 'null'
maxLength: 200
description: Optional human-readable label for your dashboard.
WebhookCreated:
allOf:
- $ref: '#/components/schemas/Webhook'
- type: object
required:
- secret
- hint
properties:
secret:
type: string
description: '**Shown once.** Copy and store server-side immediately. Used to sign every outgoing delivery.'
hint:
type: string
description: Signature-verification reminder.
WebhookQuota:
type: object
required:
- maxEndpoints
- maxEventsPerDay
properties:
maxEndpoints:
type: number
description: Max simultaneous active webhook endpoints on this tier.
maxEventsPerDay:
type: number
description: Max event deliveries per UTC day on this tier.
additionalProperties: false
WebhookFilter:
oneOf:
- type: object
required:
- parcel_ids
properties:
parcel_ids:
type: array
items:
type: string
minItems: 1
maxItems: 1000
description: 'Parcels to subscribe to, 1–1000: canonical ids `state_fips:county_fips:parcel_id` (preferred; the `canonical_id` other endpoints return), legacy `SSCCC:parcel_id`, parcel UUIDs, or a bare parcel_id that names exactly ONE served parcel. parcel_id is county-scoped, so a bare id that names several parcels is refused with 422 `parcel_identity_unresolved` listing the candidate canonical ids. Stored and matched on the full identity; deliveries carry `canonical_id`.'
- type: object
required:
- state_fips
properties:
state_fips:
type: string
pattern: ^[0-9]{2}$
description: 2-digit state FIPS — subscribe to all parcels in this state.
- type: object
required:
- state_fips
- county_fips
properties:
state_fips:
type: string
pattern: ^[0-9]{2}$
county_fips:
type: string
pattern: ^[0-9]{3}$
description: 3-digit county FIPS (within the state) — subscribe to all parcels in this county.
description: 'Shape varies with filter_kind. parcel_ids: explicit list. state_fips: all parcels in a state. county_fips: all parcels in a county within a state.'
Problem:
type: object
description: 'THE error body of every /api/v1 endpoint (RFC 7807 problem details, served as `application/problem+json`). `code` is the stable machine-readable identifier (e.g. invalid_parameter, authentication_required, account_required, monthly_cap_reached, query_timeout, not_found, method_not_allowed); `detail` is human-readable and never contains database or driver text. Validation failures add `errors: [{param, message}]`. `request_id` identifies the request for support; every error response carries it, and the same value in the `X-Request-Id` header. Per-code members (e.g. `reason`, `retry_after`, `used` / `limit` / `plan` / `upgrade`, `allow`) sit beside the core members. Exception: an x402 `402 Payment Required` keeps the x402 protocol envelope (`x402Version`, `accepts`).'
required:
- type
- title
- status
- detail
- code
properties:
type:
type: string
title:
type: string
status:
type: integer
detail:
type: string
code:
type: string
description: Stable machine-readable code.
example: invalid_parameter
reason:
type: string
description: Finer reason for `code`, e.g. people_data_requires_account.
errors:
type: array
description: Per-parameter validation failures (400 invalid_parameter).
items:
type: object
required:
- param
- message
properties:
param:
type: string
example: limit
message:
type: string
example: must be >= 1
request_id:
type: string
description: Support handle for this request.
additionalProperties: true
example:
type: https://api.propraven.com/errors/invalid-parameter
title: Bad Request
status: 400
detail: 'limit: must be >= 1'
code: invalid_parameter
errors:
- param: limit
message: must be >= 1
request_id: iad1::abc123
responses:
BadRequest:
description: A query or body parameter is invalid. Nothing was read or charged.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
example:
type: https://api.propraven.com/errors/invalid-parameter
title: Bad Request
status: 400
detail: 'limit: must be >= 1'
code: invalid_parameter
errors:
- param: limit
message: must be >= 1
NotFound:
description: The resource (or the endpoint) does not exist.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
example:
type: https://api.propraven.com/errors/not-found
title: Not Found
status: 404
detail: No API endpoint at /api/v1/doesnotexist.
code: not_found
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
MethodNotAllowed:
description: The endpoint exists but does not support this method. `Allow` lists the methods it does.
headers:
Allow:
description: Methods this endpoint supports.
schema:
type: string
example: GET, HEAD, OPTIONS
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
example:
type: https://api.propraven.com/errors/method-not-allowed
title: Method Not Allowed
status: 405
detail: 'DELETE is not supported on /api/v1/parcels/[id]. Allowed: GET, HEAD, OPTIONS.'
code: method_not_allowed
allow:
- GET
- HEAD
- OPTIONS
Unauthorized:
description: Missing, malformed or invalid credential.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
example:
type: https://api.propraven.com/errors/authentication-required
title: Unauthorized
status: 401
detail: Provide an API key in the Authorization header ('Bearer pz_...') or sign in via the web dashboard.
code: authentication_required
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
InternalError:
description: Unexpected server error. The body never carries database or driver text.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
example:
type: https://api.propraven.com/errors/internal-error
title: Internal Server Error
status: 500
detail: An internal error occurred.
code: internal_error
request_id: iad1::abc123
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
RateLimitExceeded:
description: Rate limit exceeded.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
example:
type: https://api.propraven.com/errors/rate-limit-exceeded
title: Rate limit exceeded
status: 429
detail: Rate limit exceeded
code: rate_limit_exceeded
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: pz_*
description: 'API key with pz_ prefix. Pass as: Authorization: Bearer pz_your_api_key'
sessionCookie:
type: apiKey
in: cookie
name: sb-<project-ref>-auth-token
description: The signed-in web session (Supabase auth cookie) set by signing in at https://propraven.com/sign-in. Used only by account-scoped dashboard routes; an API key is not accepted on those routes.
externalDocs:
description: 'Connect your agent to PropRaven: the MCP server, the discover -> preview -> pay (x402) flow, and pricing.'
url: https://propraven.com/docs/agents