Oppy Events API and Automation Rules
The Events Timeline is how external tools talk to Oppy. Every time something happens in a business (a payment, a form submission, a deal closing), an event can be sent to Oppy, and Automation Rules respond to it automatically: no polling, no manual checking, no copy-pasting between systems.
Who this is for: anyone who wants to understand how Oppy connects to the rest of a tech stack: a current customer wiring up a tool, a prospect evaluating whether Oppy fits their stack, or a developer implementing the integration.
Tip
New to Oppy? Here’s what this unlocks: any tool that can make an HTTP request (Stripe, Salesforce, HubSpot, a CRM, a form builder, Zapier, or custom code) can notify Oppy the moment something happens, and Oppy can act on it instantly: send a message, update a contact, alert a team, or kick off a workflow. No custom integration code required on Oppy’s side.
3 Steps to Post Your First Event
Step 1: Get your API key
Go to Settings → API Keys and copy your key.
Step 2: Send an event
Most senders can set a custom header. Use your account API key:
curl -X POST https://io.oppy.pro/api/events \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"event_type": "payment_received",
"message": "New payment from Jane Smith",
"source": "stripe"
}'
If your sender can’t set custom headers (common with CRMs, form tools, and Zapier-style webhooks), pass a scoped ingress token in the URL instead. No headers needed at all:
curl -X POST "https://io.oppy.pro/api/events?token=YOUR_INGRESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event_type": "payment_received",
"message": "New payment from Jane Smith",
"source": "stripe"
}'
An ingress token is tied to one source name, so events sent with it are automatically namespaced to that source (see below) even if the payload never mentions it.
Step 3: Check your Timeline
Go to Events. Your event will appear instantly.
That’s it. Only event_type is required. Add message, source, and payload to make events more useful.
Request Fields
Endpoint: POST https://io.oppy.pro/api/events
Two ways to authenticate:
| Mode | How | Best for |
|---|---|---|
| Header | X-API-Key: YOUR_API_KEY |
Your full account-admin API key. Use when the sender lets you set custom headers. |
| Query token |
?token=YOUR_INGRESS_TOKEN on the URL |
A scoped “events ingress” token tied to one source name. Use when the sender can’t set custom headers (most CRMs, Zapier, Make.com, form tools). |
Get an ingress token from Settings → API Keys, or ask your Oppy concierge to create one scoped to a source (e.g. “stripe”, “hubspot”, “sierra”).
| Field | Required | Description |
|---|---|---|
event_type |
Yes | What happened: payment_received, form_submitted, deal_closed_won
|
source |
No | Where it came from: stripe, salesforce, activecampaign
|
message |
No | Human-readable summary shown in the timeline |
payload |
No | Any JSON (the full webhook body, custom fields, anything) |
description |
No | Longer description for context |
metadata |
No | Internal metadata (not shown in timeline UI) |
status |
No |
active (default), completed, pending, inactive
|
How Oppy Names Your Event
You don’t have to send a perfectly-formatted event_type. Oppy looks for the event name in common fields (event_type, event, type, eventType, or a header some vendors send) and auto-detects it from whatever your sender provides.
Whatever name it finds gets namespaced to your source, so different vendors never collide. A payment.succeeded event sent with source: "stripe" (or a Stripe-scoped token) lands as stripe.payment.succeeded. The same event name from a different source stays completely separate in your Timeline and in Automation Rules.
Verification Handshakes
Some platforms (Slack, Monday.com, and similar) send a one-time “challenge” request to confirm the endpoint is real before they’ll start delivering events. POST /api/events recognizes these automatically and echoes the challenge back, so you can point Slack/Monday’s webhook setup straight at the endpoint with no extra configuration.
Sending Many Events at Once
Some integrations batch multiple events into one request. Send a JSON array instead of a single object and Oppy will fan each item out as its own event:
[
{ "event_type": "contact_updated", "source": "hubspot", "payload": { "id": "1" } },
{ "event_type": "deal_stage_changed", "source": "hubspot", "payload": { "id": "2" } }
]
Limits
To keep things fast and fair for everyone: up to 120 events per minute per source, and 128KB per request. If you’re sending a high-volume integration and expect to need more, talk to your Oppy contact.
Real-World Examples
Stripe: Payment received
{
"event_type": "payment_received",
"message": "Payment of $49 received",
"source": "stripe",
"payload": {
"customer_email": "jane@example.com",
"amount": 4900,
"plan": "pro"
}
}
Salesforce: Deal closed
{
"event_type": "deal_closed_won",
"message": "Deal closed: Acme Corp Enterprise",
"source": "salesforce",
"payload": {
"opportunity_id": "006xx000001abc",
"account_name": "Acme Corp",
"amount": 25000,
"owner_email": "rep@yourco.com",
"stage": "Closed Won"
}
}
ActiveCampaign: Contact tagged
{
"event_type": "contact_tag_added",
"message": "Contact tagged as hot-lead",
"source": "activecampaign",
"payload": {
"contact_email": "buyer@example.com",
"tag": "hot-lead",
"list": "Sales Pipeline",
"automation": "Lead Scoring v2"
}
}
Typeform: Form submitted
{
"event_type": "form_submitted",
"message": "New lead form submitted",
"source": "typeform",
"payload": {
"name": "Alex Johnson",
"email": "alex@example.com",
"interest": "Enterprise plan"
}
}
Calendly: Appointment booked
{
"event_type": "appointment_booked",
"message": "Demo call booked for Friday 2pm",
"source": "calendly",
"payload": {
"guest_email": "prospect@company.com",
"meeting_at": "2026-04-01T14:00:00Z"
}
}
Code Snippets
JavaScript / Node.js
await fetch('https://io.oppy.pro/api/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.OPPY_API_KEY,
},
body: JSON.stringify({
event_type: 'payment_received',
source: 'stripe',
message: 'New payment received',
payload: { customer_email: 'jane@example.com', amount: 4900 },
}),
});
Python
import requests
requests.post(
'https://io.oppy.pro/api/events',
headers={
'Content-Type': 'application/json',
'X-API-Key': OPPY_API_KEY,
},
json={
'event_type': 'deal_closed_won',
'source': 'salesforce',
'message': 'Deal closed: Acme Corp',
'payload': {'account_name': 'Acme Corp', 'amount': 25000},
},
)
Zapier / Make.com (no code)
Use Webhooks by Zapier → POST or Make.com HTTP module to POST to https://io.oppy.pro/api/events with your API key in the X-API-Key header.
Automation Rules
Once events appear in the Timeline, create rules to respond automatically:
- Go to Automations in the sidebar
- Create a new rule matching your
event_type - Set an action: send a message, update a contact, notify your team
Example: When payment_received arrives → Oppy looks up the contact and sends a personalized thank-you email.
For the plain-English, business-use-case version of this (no code, just outcomes), see Public Events & Automation Rules: A Guide to What’s Possible.
Need Help?
- Ask your Oppy concierge (blue icon, bottom right): it can build automations for you
- Chat with AI about this guide: