Skip to content

Delivery System Integration

The core of OpenProspect: How we deliver qualified leads to your system.


📦 Overview

The Delivery System is the bridge between OpenProspect's data engine and your internal systems (CRM, Outreach tools, Database). It handles the reliable transfer of companies and prospects that match your specific criteria.

How It Works

graph LR
    A[OpenProspect Engine] -->|Finds & Qualifies| B(Qualified Company)
    B --> C{Delivery Mode}
    C -->|Push| D[Webhook POST]
    D -->|Real-time| E[Your Server]
    C -->|Pull| F[Store in Database]
    G[Your Server] -->|GET Request| F
  1. Discovery: Our engine finds companies matching your Ideal Customer Profile (ICP).
  2. Qualification: We apply your specific qualification rules (technographics, firmographics).
  3. Delivery: When a company is qualified, we deliver it to you immediately.

Choose Your Integration Pattern

Pattern Type Best For Pros Cons
Push (Webhooks) Real-time CRMs, Slack/Teams, Zapier Immediate data, event-driven Requires public endpoint
Pull (API) Batch Data Warehouses, nightly syncs Control over timing, bulk processing Not real-time

🚀 Push Model (Webhooks)

In the Push model, OpenProspect sends an HTTP POST request to your server the moment a company is qualified.

Tip: Use webhook.site to inspect payloads and test your integration before writing code.

1. Configure Your Destination

You can configure a webhook destination via the API:

curl -X POST "https://api.openprospect.io/api/v1/deliveries/123/destinations" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "webhook",
    "url": "https://your-api.com/webhooks/openprospect",
    "auth_type": "bearer",
    "auth_token": "your-secret-token"
  }'

2. Webhook Payload

We send a JSON payload with the company and its prospects.

{
  "event": "delivery.company_qualified",
  "delivery_id": "del_123abc",
  "timestamp": "2025-11-30T12:00:00Z",
  "data": {
    "company": {
      "id": "comp_xyz789",
      "name": "Acme Corp",
      "domain": "acme.com",
      "industry": "Software",
      "size": "50-200",
      "location": "San Francisco, CA",
      "linkedin_url": "https://linkedin.com/company/acme-corp",
      "technologies": ["HubSpot", "AWS", "React"]
    },
    "prospects": [
      {
        "id": "pros_456def",
        "first_name": "Jane",
        "last_name": "Doe",
        "title": "CTO",
        "email": "jane.doe@acme.com",
        "linkedin_url": "https://linkedin.com/in/janedoe"
      }
    ],
    "qualification_score": 85,
    "match_reasons": [
      "Uses HubSpot",
      "Revenue > $10M",
      "Decision Maker found"
    ]
  }
}

3. Handling Webhooks

Your server should:

  1. Accept POST requests.
  2. Return a 200 OK status code immediately.
  3. Process the data asynchronously if possible.

Example Receiver

from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.post("/webhooks/openprospect")
async def receive_webhook(request: Request):
    # 1. Verify Authentication (Optional but recommended)
    auth_header = request.headers.get("Authorization")
    if auth_header != "Bearer your-secret-token":
        raise HTTPException(status_code=401)

    # 2. Parse Payload
    payload = await request.json()

    # 3. Process Data
    company = payload["data"]["company"]
    print(f"Received qualified lead: {company['name']}")

    # 4. Return 200 OK
    return {"status": "received"}
const express = require('express');
const app = express();

app.use(express.json());

app.post('/webhooks/openprospect', (req, res) => {
    // 1. Verify Authentication
    const authHeader = req.headers.authorization;
    if (authHeader !== 'Bearer your-secret-token') {
        return res.status(401).send('Unauthorized');
    }

    // 2. Process Data
    const { company } = req.body.data;
    console.log(`Received qualified lead: ${company.name}`);

    // 3. Return 200 OK
    res.status(200).json({ status: 'received' });
});
import express, { Request, Response } from 'express';
const app = express();

app.use(express.json());

interface WebhookPayload {
  event: string;
  data: {
    company: { name: string; [key: string]: any };
    prospects: any[];
  };
}

app.post('/webhooks/openprospect', (req: Request, res: Response) => {
    // 1. Verify Authentication
    const authHeader = req.headers.authorization;
    if (authHeader !== 'Bearer your-secret-token') {
        return res.status(401).send('Unauthorized');
    }

    // 2. Process Data
    const payload = req.body as WebhookPayload;
    const { company } = payload.data;
    console.log(`Received qualified lead: ${company.name}`);

    // 3. Return 200 OK
    res.status(200).json({ status: 'received' });
});
[HttpPost("webhooks/openprospect")]
public IActionResult ReceiveWebhook([FromBody] JsonElement payload, [FromHeader] string authorization)
{
    // 1. Verify Authentication
    if (authorization != "Bearer your-secret-token")
    {
        return Unauthorized();
    }

    // 2. Process Data
    // Note: In a real app, define a class for the payload
    var companyName = payload.GetProperty("data")
                             .GetProperty("company")
                             .GetProperty("name")
                             .GetString();

    Console.WriteLine($"Received qualified lead: {companyName}");

    // 3. Return 200 OK
    return Ok(new { status = "received" });
}

4. Reliability & Retries

If your server returns an error (5xx) or times out:

  • We retry 5 times with exponential backoff.
  • Retry intervals: 1m, 5m, 15m, 1h, 6h.
  • After 5 failures, the delivery is marked as failed.

📥 Pull Model (API Access)

In the Pull model, you request data from our API on your own schedule.

1. Fetch Delivered Companies

Get all companies delivered for a specific prospect search, with optional time-based filtering for incremental syncs.

# Get all delivered companies
curl -X GET "https://api.openprospect.io/api/v1/deliveries/{prospect_search_id}/companies?limit=50" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}"

# Get only companies delivered since last sync (incremental)
curl -X GET "https://api.openprospect.io/api/v1/deliveries/{prospect_search_id}/companies?delivered_since=2025-01-15T00:00:00Z&limit=50" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}"

Query Parameters:

Parameter Type Description
delivered_since ISO 8601 datetime Only return companies delivered after this timestamp
limit integer (1-100) Number of results per page (default: 50)
offset integer Number of results to skip for pagination

Tip: For CRM integrations, store the delivered_at timestamp of the last synced company and use it as delivered_since in subsequent requests.

2. Pagination

We use standard limit/offset pagination.

  • limit: Number of items to return (default 20, max 100).
  • offset: Number of items to skip.

Response:

{
  "items": [...],
  "total": 150,
  "limit": 20,
  "offset": 0
}

🛡️ Best Practices

  1. Idempotency: Webhooks might be delivered more than once. Use delivery_id or company.id to prevent duplicate processing.
  2. Security: Always use authentication for your webhook endpoints.
  3. Rate Limiting: When using the Pull API, respect the rate limits headers (RateLimit-Remaining).

🛠️ Managing Deliveries

You can programmatically manage your delivery configurations using the API.

List Deliveries

Get all your configured deliveries.

curl -X GET "https://api.openprospect.io/api/v1/deliveries" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}"

Create a Delivery

Create a new delivery configuration.

curl -X POST "https://api.openprospect.io/api/v1/deliveries" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CRM Sync",
    "status": "active",
    "schedule": "immediate"
  }'

Add a Destination

Add a webhook or API destination to a delivery.

curl -X POST "https://api.openprospect.io/api/v1/deliveries/{id}/destinations" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "webhook",
    "url": "https://your-api.com/webhooks/openprospect",
    "auth_type": "bearer",
    "auth_token": "your-secret-token"
  }'

Get Delivery Details

curl -X GET "https://api.openprospect.io/api/v1/deliveries/{id}" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}"

Update a Delivery

curl -X PUT "https://api.openprospect.io/api/v1/deliveries/{id}" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CRM Sync (Updated)",
    "status": "paused"
  }'

Delete a Delivery

curl -X DELETE "https://api.openprospect.io/api/v1/deliveries/{id}" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}"

Remove a Destination

curl -X DELETE "https://api.openprospect.io/api/v1/deliveries/{id}/destinations/{dest_id}" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}"