Documentation

Learn how to integrate APIVine APIs into your applications. All our APIs are available through RapidAPI.

Quick Start

Get up and running in minutes

Code Examples

Sample code in multiple languages

API Reference

Detailed endpoint documentation

Response Schemas

Understand response structures

Getting Started

1. Sign up for RapidAPI

All APIVine APIs are hosted on RapidAPI. Create a free account to get started.

Sign up for RapidAPI

2. Subscribe to an API

Browse our APIs and subscribe to the one you need. All APIs include a free tier for testing.

Browse APIs

3. Get your API Key

Once subscribed, you'll receive an API key that you'll use to authenticate requests. Find your key in the RapidAPI dashboard.

Authentication

All API requests require authentication via RapidAPI. Include these headers with every request:

json
// Required headers for all requests
{
  "X-RapidAPI-Key": "your-api-key-here",
  "X-RapidAPI-Host": "api-host-here"
}

Making Requests

All endpoints follow the same pattern — pass your RapidAPI key in the headers and your query as URL parameters. Here are examples using the /lookup endpoint to fetch a full property report:

javascript
// JavaScript — look up a property by BBL
const response = await fetch(
  'https://new-york-city-violation-alerts.p.rapidapi.com/lookup?bbl=1004777501',
  {
    headers: {
      'X-RapidAPI-Key': 'your-api-key',
      'X-RapidAPI-Host': 'new-york-city-violation-alerts.p.rapidapi.com'
    }
  }
);
const data = await response.json();
// data.property  — PLUTO fields (address, borough, year_built, …)
// data.violations / data.complaints / data.permits — arrays
// data.summary   — { violation_count, complaint_count, permit_count }
python
# Python — look up a property by address
import requests

response = requests.get(
    'https://new-york-city-violation-alerts.p.rapidapi.com/lookup',
    params={'address': '350 Fifth Ave'},
    headers={
        'X-RapidAPI-Key': 'your-api-key',
        'X-RapidAPI-Host': 'new-york-city-violation-alerts.p.rapidapi.com'
    }
)
data = response.json()
print(data['property']['bbl'])
print(data['summary'])

Available endpoints

  • GET /lookup — Full report by address, BBL, or BIN
  • GET /violations — DOB + OATH/ECB violations by BIN
  • GET /complaints — DOB complaints by BIN
  • GET /permits — DOB permits by BIN
  • GET /search — Search cached properties by address, BBL, or BIN
  • GET /changes — Poll for new records since a given timestamp
  • GET /landlord — All properties owned by a name or LLC
  • GET /timeline — Violations, complaints, and permits as a single chronological feed
  • GET /neighborhood — Aggregate stats for a zip code

Response Format

All API responses are returned in JSON format with a consistent structure:

json
// Successful response
{
  "status": "success",
  "count": 10,
  "data": [...],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 100
  }
}

// Error response
{
  "status": "error",
  "code": "INVALID_PARAMETER",
  "message": "The 'address' parameter is required."
}

Error Handling

The API uses standard HTTP status codes to indicate success or failure:

Status CodeMeaningDescription
200OKRequest successful
400Bad RequestInvalid request parameters
401UnauthorizedInvalid or missing API key
403ForbiddenNot subscribed to this API
429Too Many RequestsRate limit exceeded
500Server ErrorInternal server error

Rate Limits

Rate limits vary by subscription plan. Check the specific API page for details on limits. When you exceed the rate limit, you'll receive a 429 status code.

Rate Limit Headers

Each response includes headers indicating your current rate limit status:

  • X-RateLimit-Limit - Maximum requests allowed
  • X-RateLimit-Remaining - Requests remaining
  • X-RateLimit-Reset - Time when the limit resets

Polling for Changes

Instead of re-fetching a full property report on every request, use the /changes endpoint to retrieve only what is new since your last poll. Store the timestamp of your last successful request and pass it as the since parameter on the next call.

How it works

  1. Do an initial full lookup with GET /lookup?bbl=... and record Date.now().
  2. On a schedule (e.g. every hour), call GET /changes?bbl=...&since=<last_poll>.
  3. If violation_count, complaint_count, or permit_count is > 0, process the new records.
  4. Update your stored timestamp to the current time.
javascript
// JavaScript — poll for new violations every hour
const BBL = '1004777501'
let lastPoll = new Date(Date.now() - 3600_000).toISOString() // 1 hour ago

async function pollChanges() {
  const url = new URL('https://new-york-city-violation-alerts.p.rapidapi.com/changes')
  url.searchParams.set('bbl', BBL)
  url.searchParams.set('since', lastPoll)

  const res = await fetch(url, {
    headers: {
      'X-RapidAPI-Key': 'your-api-key',
      'X-RapidAPI-Host': 'new-york-city-violation-alerts.p.rapidapi.com'
    }
  })

  const data = await res.json()

  if (data.violation_count > 0 || data.complaint_count > 0) {
    console.log(`${data.violation_count} new violations, ${data.complaint_count} new complaints`)
    // handle data.violations, data.complaints, data.permits ...
  }

  lastPoll = new Date().toISOString()
}

setInterval(pollChanges, 60 * 60 * 1000) // every hour
python
# Python — poll for new violations
import requests
from datetime import datetime, timedelta, timezone

BBL = '1004777501'
last_poll = (datetime.now(timezone.utc) - timedelta(hours=1)).isoformat()

def poll_changes():
    global last_poll
    response = requests.get(
        'https://new-york-city-violation-alerts.p.rapidapi.com/changes',
        params={'bbl': BBL, 'since': last_poll},
        headers={
            'X-RapidAPI-Key': 'your-api-key',
            'X-RapidAPI-Host': 'new-york-city-violation-alerts.p.rapidapi.com'
        }
    )
    data = response.json()

    if data['violation_count'] > 0 or data['complaint_count'] > 0:
        print(f"{data['violation_count']} new violations")
        # process data['violations'], data['complaints'], data['permits']

    last_poll = datetime.now(timezone.utc).isoformat()

Response structure

json
{
  "bbl": "1004777501",
  "since": "2025-01-01T00:00:00Z",
  "violations": [ /* new ViolationResponse objects */ ],
  "complaints": [ /* new ComplaintResponse objects */ ],
  "permits":    [ /* new PermitResponse objects */ ],
  "violation_count": 1,
  "complaint_count": 0,
  "permit_count": 0
}

Landlord Lookup

Use GET /landlord to find every NYC property owned by a given person or LLC. Searches the PLUTO dataset by owner name (partial, case-insensitive match). New properties found upstream are cached automatically.

Parameters

  • owner required — Owner name or LLC (partial match, e.g. TRUMP or BLACKSTONE)
  • limit — Max properties to return (1–200, default 50)
javascript
// JavaScript — find all properties owned by an LLC
const response = await fetch(
  'https://new-york-city-violation-alerts.p.rapidapi.com/landlord?owner=STUY+TOWN&limit=100',
  {
    headers: {
      'X-RapidAPI-Key': 'your-api-key',
      'X-RapidAPI-Host': 'new-york-city-violation-alerts.p.rapidapi.com'
    }
  }
)
const data = await response.json()
// data.owner_query — normalized search term
// data.count       — number of matching properties
// data.properties  — array of property objects with PLUTO fields
python
# Python — portfolio lookup for a landlord
import requests

r = requests.get(
    'https://new-york-city-violation-alerts.p.rapidapi.com/landlord',
    params={'owner': 'BLACKSTONE', 'limit': 200},
    headers={
        'X-RapidAPI-Key': 'your-api-key',
        'X-RapidAPI-Host': 'new-york-city-violation-alerts.p.rapidapi.com'
    }
)
data = r.json()
for prop in data['properties']:
    print(prop['bbl'], prop['address'], prop['assessed_total_value'])

Property Timeline

Use GET /timeline to get violations, complaints, and permits for a BBL merged into a single event feed sorted newest-first. Each event has a type field (violation, complaint, or permit) so you can filter or color-code in your UI.

Parameters

  • bbl required — Borough-Block-Lot identifier (e.g. 1000477501)
javascript
// JavaScript — render a property history feed
const response = await fetch(
  'https://new-york-city-violation-alerts.p.rapidapi.com/timeline?bbl=1000477501',
  {
    headers: {
      'X-RapidAPI-Key': 'your-api-key',
      'X-RapidAPI-Host': 'new-york-city-violation-alerts.p.rapidapi.com'
    }
  }
)
const { timeline, event_count } = await response.json()
console.log(`${event_count} events`)
for (const event of timeline) {
  // event.type        — 'violation' | 'complaint' | 'permit'
  // event.date        — ISO date string (or null)
  // event.title       — short label (violation_type, complaint_type, permit_type)
  // event.description — longer description
  // event.status      — current status
  console.log(event.date, event.type, event.title)
}
python
# Python — due diligence timeline for a BBL
import requests

r = requests.get(
    'https://new-york-city-violation-alerts.p.rapidapi.com/timeline',
    params={'bbl': '1000477501'},
    headers={
        'X-RapidAPI-Key': 'your-api-key',
        'X-RapidAPI-Host': 'new-york-city-violation-alerts.p.rapidapi.com'
    }
)
data = r.json()
for event in data['timeline']:
    print(f"[{event['type']}] {event['date']} — {event['title']}")

Neighborhood Stats

Use GET /neighborhood to get aggregate stats for an NYC zip code. The pluto_summary field (total properties, units, average assessed value, average year built) comes directly from NYC Open Data and covers all properties in the zip. Violation, complaint, and permit rates are computed from properties already cached locally — call /lookup on individual properties first to warm the cache.

Parameters

  • zip_code required — NYC zip code (e.g. 10001)
javascript
// JavaScript — site selection analytics for a zip code
const response = await fetch(
  'https://new-york-city-violation-alerts.p.rapidapi.com/neighborhood?zip_code=10001',
  {
    headers: {
      'X-RapidAPI-Key': 'your-api-key',
      'X-RapidAPI-Host': 'new-york-city-violation-alerts.p.rapidapi.com'
    }
  }
)
const data = await response.json()
// data.pluto_summary.total_properties    — all properties in zip (from PLUTO)
// data.pluto_summary.avg_assessed_total_value
// data.violation_rate  — avg violations per cached property
// data.top_violation_types  — [{ type, count }, ...]
python
# Python — compare neighborhoods by violation rate
import requests

HOST = 'new-york-city-violation-alerts.p.rapidapi.com'
HEADERS = {
    'X-RapidAPI-Key': 'your-api-key',
    'X-RapidAPI-Host': HOST
}

for zip_code in ['10001', '10002', '10003']:
    r = requests.get(
        f'https://{HOST}/neighborhood',
        params={'zip_code': zip_code},
        headers=HEADERS
    )
    d = r.json()
    print(f"{zip_code}: {d['violation_rate']} violations/property, "
          f"{d['pluto_summary'].get('total_properties')} total properties")

Property Owner Lookup

The National Property Owner Lookup API is a separate API with its own RapidAPI subscription and host (national-property-owner-lookup.p.rapidapi.com). It resolves property ownership from county assessor open data across multiple US counties. Use GET /owner/lookup to find who owns an address, and GET /owner/portfolio to find every property a person or LLC owns within a county.

Supported counties

Coverage currently spans New York City, Philadelphia, Washington DC, and Boston, with more counties added over time. Call GET /owner/counties for the live list — its slug values are what you pass as the county parameter. Every county returns the identical record shape.

Parameters

/owner/lookup

  • address required — Street address to look up (matched as a case-insensitive substring)
  • county required — County slug from /owner/counties
  • limit — Max records to return (1–100, default 25)

/owner/portfolio

  • name required — Owner name or LLC to search (partial match)
  • county required — County slug from /owner/counties
  • limit — Max properties to return (1–200, default 50)
javascript
// JavaScript — who owns this property?
const response = await fetch(
  'https://national-property-owner-lookup.p.rapidapi.com/owner/lookup?address=350+5+Avenue&county=nyc',
  {
    headers: {
      'X-RapidAPI-Key': 'your-api-key',
      'X-RapidAPI-Host': 'national-property-owner-lookup.p.rapidapi.com'
    }
  }
)
const data = await response.json()
// data.results — array of normalized owner records
// each record: owner_name, address, parcel_id, assessed_value,
//              year_built, owner_mailing_address, owner_occupied
python
# Python — skip-trace every property an LLC owns
import requests

HOST = 'national-property-owner-lookup.p.rapidapi.com'
r = requests.get(
    f'https://{HOST}/owner/portfolio',
    params={'name': 'CENTRAL CAPITAL GROUP', 'county': 'philadelphia', 'limit': 200},
    headers={
        'X-RapidAPI-Key': 'your-api-key',
        'X-RapidAPI-Host': HOST
    }
)
data = r.json()
for prop in data['results']:
    print(prop['address'], '—', prop['owner_mailing_address'])

Note

County assessor portals deliberately omit owner names for many jurisdictions. This API only covers counties that publish owner data openly. Fields a county does not publish — such as owner_mailing_address or owner_occupied — are returned as null rather than omitted, so the response shape stays stable across counties.

Business Entity Lookup

The US Business Entity Lookup API is a separate API with its own RapidAPI subscription and host (us-business-entity-lookup.p.rapidapi.com). It unifies state Secretary of State corporation and LLC registries behind one interface. Use GET /entity/search to find entities by name, and GET /entity/lookup to resolve a single entity by its state registry ID.

Supported states

Coverage currently spans New York, with more states added over time. Call GET /entity/states for the live list — its slug values are what you pass as the state parameter. Every state returns the identical record shape.

Parameters

/entity/search

  • name required — Entity name to search (matched as a case-insensitive substring)
  • state required — State slug from /entity/states
  • limit — Max entities to return (1–100, default 25)

/entity/lookup

  • registry_id required — State registry ID / file number (e.g. NY DOS ID)
  • state required — State slug from /entity/states
javascript
// JavaScript — find an LLC by name
const response = await fetch(
  'https://us-business-entity-lookup.p.rapidapi.com/entity/search?name=EMPIRE+STATE+REALTY&state=ny',
  {
    headers: {
      'X-RapidAPI-Key': 'your-api-key',
      'X-RapidAPI-Host': 'us-business-entity-lookup.p.rapidapi.com'
    }
  }
)
const data = await response.json()
// data.results — array of normalized entity records
// each record: entity_name, entity_type, status, formation_date,
//              jurisdiction, county, registered_agent, registered_agent_address
python
# Python — resolve a single entity by its registry ID
import requests

HOST = 'us-business-entity-lookup.p.rapidapi.com'
r = requests.get(
    f'https://{HOST}/entity/lookup',
    params={'registry_id': '4424185', 'state': 'ny'},
    headers={
        'X-RapidAPI-Key': 'your-api-key',
        'X-RapidAPI-Host': HOST
    }
)
entity = r.json()
print(entity['entity_name'], '—', entity['status'])
print('Registered agent:', entity['registered_agent_address'])

Note

States publish business-registry data at very different depths. New York's open data covers active corporations and LLCs and exposes the DOS process agent — the state's service-of-process contact, the open-data equivalent of a registered agent — but not officers/directors. Fields a state does not publish, such as officers, are returned as null rather than omitted, so the response shape stays stable across states.

Website Screenshot

Use GET /screenshot to capture a full-page screenshot of any public website. The page is rendered in a headless Chromium browser and the result is returned as a base64-encoded image — ready to pipe directly into a vision model or save to disk.

Parameters

  • url required — Full URL to screenshot (must start with http:// or https://)
  • full_page — Capture the entire page height, not just the visible viewport (default true)
  • format — Image format: png or jpeg (default png)
  • width — Viewport width in pixels, 320–2560 (default 1280)
javascript
// JavaScript — screenshot a page and pass it to a vision model
const response = await fetch(
  'https://website-screenshot.p.rapidapi.com/screenshot?url=https%3A%2F%2Fexample.com&full_page=true',
  {
    headers: {
      'X-RapidAPI-Key': 'your-api-key',
      'X-RapidAPI-Host': 'website-screenshot.p.rapidapi.com'
    }
  }
)
const data = await response.json()
// data.title      — page <title> text
// data.screenshot — base64-encoded PNG/JPEG string
// data.format     — 'png' or 'jpeg'
// data.url        — the URL that was screenshotted

// Decode and save to disk (Node.js)
const fs = require('fs')
fs.writeFileSync('screenshot.png', Buffer.from(data.screenshot, 'base64'))
python
# Python — screenshot a page and feed it to GPT-4o or Claude
import requests, base64, openai

HOST = 'website-screenshot.p.rapidapi.com'
r = requests.get(
    f'https://{HOST}/screenshot',
    params={'url': 'https://example.com', 'full_page': 'true', 'width': '1280'},
    headers={
        'X-RapidAPI-Key': 'your-api-key',
        'X-RapidAPI-Host': HOST
    }
)
data = r.json()

# Save to disk
with open('screenshot.png', 'wb') as f:
    f.write(base64.b64decode(data['screenshot']))

# Or pass straight to a vision model
client = openai.OpenAI()
reply = client.chat.completions.create(
    model='gpt-4o',
    messages=[{
        'role': 'user',
        'content': [
            {'type': 'text', 'text': 'Describe the design and layout of this page.'},
            {'type': 'image_url', 'image_url': {
                'url': f"data:image/{data['format']};base64,{data['screenshot']}"
            }}
        ]
    }]
)
print(reply.choices[0].message.content)

Response structure

json
{
  "url": "https://example.com",
  "title": "Example Domain",
  "format": "png",
  "screenshot": "iVBORw0KGgoAAAANSUhEUgAA..."  // base64-encoded image
}

Notes

  • The browser waits for network idle before capturing, so JavaScript-rendered content (SPAs, lazy images) is fully visible.
  • Timeout is 30 seconds. Pages that never reach network idle (e.g. infinite WebSocket streams) will return a 422 error.
  • Only public URLs are supported. Private IPs and localhost are blocked.
  • Use format=jpeg for smaller payloads on photo-heavy pages; use format=png for crisp text and UI screenshots.

Ready to get started?

Browse our APIs and start building today.

Browse APIs