Docs
API Reference

API Reference

Integrate Plotwise with your systems using our REST API.

The Plotwise API allows you to programmatically access permit data, manage your watchlist, and integrate with your existing systems.

API Overview

Base URL

https://api.plotwise.us/v1

Authentication

All API requests require authentication via API key:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.plotwise.us/v1/permits

Response Format

All responses are JSON:

{
  "data": { ... },
  "meta": {
    "page": 1,
    "per_page": 25,
    "total": 150
  }
}

Error Format

{
  "error": {
    "code": "invalid_request",
    "message": "Description of what went wrong"
  }
}

Getting Started

1. Create API Key

  1. Go to Organization Settings → Developers
  2. Click "Create API Key"
  3. Name your key (e.g., "CRM Integration")
  4. Select permissions
  5. Copy key (shown only once)

2. Test Connection

curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.plotwise.us/v1/me

Successful response:

{
  "data": {
    "organization_id": "org_xxx",
    "organization_name": "Your Company",
    "permissions": ["read", "write"]
  }
}

Core Endpoints

Permits

List Watchlist Permits

GET /v1/permits

Query Parameters:

ParameterTypeDescription
pageintegerPage number (default: 1)
per_pageintegerResults per page (max: 100)
statusstringFilter by status
updated_sincedatetimeFilter by update date

Example:

curl -H "Authorization: Bearer $API_KEY" \
  "https://api.plotwise.us/v1/permits?status=active&per_page=50"

Response:

{
  "data": [
    {
      "uuid": "abc-123-def",
      "permit_number": "BLD-24-001234",
      "status": "In Review",
      "type": "Building",
      "description": "New commercial building",
      "address": "123 Main St, Miami, FL",
      "filed_date": "2024-01-15",
      "updated_at": "2024-01-20T10:30:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 50,
    "total": 127
  }
}

Get Permit Details

GET /v1/permits/{uuid}

Response includes:

  • Basic permit information
  • Current status
  • Associated parties
  • Status history
  • Your notes and tags

Get Permit History

GET /v1/permits/{uuid}/history

Returns status change history for the permit.

Watchlist Management

Add to Watchlist

POST /v1/watchlist

Request Body:

{
  "permit_number": "BLD-24-001234",
  "jurisdiction": "miami-dade"
}

Or by UUID:

{
  "permit_uuid": "abc-123-def"
}

Remove from Watchlist

DELETE /v1/watchlist/{permit_uuid}

Contacts

List Contacts

GET /v1/contacts

Get Contact

GET /v1/contacts/{id}

Create Contact

POST /v1/contacts

Request Body:

{
  "name": "John Smith",
  "company": "ABC Contractors",
  "email": "john@abc.com",
  "phone": "+14155551234",
  "type": "contractor"
}

Portfolio Conditions

List Conditions

GET /v1/portfolio/conditions

Get Condition Matches

GET /v1/portfolio/conditions/{id}/permits

Returns permits matching the specified condition.

Webhooks

Webhook Events

Configure webhooks to receive real-time notifications:

EventDescription
permit.status_changedPermit status updated
permit.fee_changedFee added or modified
permit.inspection_scheduledInspection date set
permit.added_to_watchlistPermit tracking started
permit.removed_from_watchlistPermit tracking ended

Webhook Payload

{
  "event": "permit.status_changed",
  "timestamp": "2024-01-23T10:45:00Z",
  "organization_id": "org_xxx",
  "data": {
    "permit_uuid": "abc-123",
    "permit_number": "BLD-24-001234",
    "previous_status": "Pending",
    "new_status": "In Review"
  }
}

Verifying Webhooks

Verify webhook signatures:

const crypto = require('crypto');
 
function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return signature === expected;
}

Rate Limits

API requests are rate limited by plan:

PlanRate Limit
Starter100 requests/minute
Professional1,000 requests/minute
EnterpriseCustom

Rate limit headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1706012345

Pagination

List endpoints support pagination:

GET /v1/permits?page=2&per_page=50

Response includes pagination metadata:

{
  "meta": {
    "page": 2,
    "per_page": 50,
    "total": 150,
    "total_pages": 3
  }
}

Error Codes

CodeStatusDescription
unauthorized401Invalid or missing API key
forbidden403Insufficient permissions
not_found404Resource doesn't exist
rate_limited429Too many requests
invalid_request400Bad request parameters
server_error500Internal server error

SDKs

JavaScript/TypeScript

npm install @plotwise/sdk
import { Plotwise } from '@plotwise/sdk';
 
const client = new Plotwise({ apiKey: 'YOUR_API_KEY' });
 
const permits = await client.permits.list({
  status: 'active',
  perPage: 50
});

Python

pip install plotwise
from plotwise import Plotwise
 
client = Plotwise(api_key='YOUR_API_KEY')
 
permits = client.permits.list(
    status='active',
    per_page=50
)

Best Practices

Caching

  • Cache permit data locally when possible
  • Use updated_since parameter for incremental sync
  • Respect cache headers in responses

Error Handling

  • Implement exponential backoff for retries
  • Handle rate limits gracefully
  • Log errors for debugging

Security

  • Never expose API keys in client-side code
  • Rotate keys periodically
  • Use minimum required permissions

Full API Documentation

Complete API documentation with interactive examples:

OpenAPI Specification: https://api.plotwise.us/docs

Includes:

  • All endpoints with full parameters
  • Interactive API explorer
  • Code examples in multiple languages
  • Schema definitions