Developers
An agent is one HTTP step
Every agent has an address. Call it from Zapier, n8n, Make, a Google Sheets cell or a script, give it the company from the step before, and get the people, their checked emails and the research back. The sentence is read once into a plan; every call after that runs the stored plan.
Zapier, n8n and Make
The same agent in each tool. Copy the agent's link from the app, add your API key, and map the company in.
One company, in the step
- 1Pick a trigger that has the company: a new row in Google Sheets, a new company in HubSpot, a form answer.
- 2Add Webhooks by Zapier, event GET. URL: the agent's link from Copy link in the app (or the one below).
- 3Under Query String Params add
domainsand insert the company's website from the trigger. Add the headerAuthorizationwithBearerand your API key. - 4Test it. The step returns JSON: one row per person with their checked email and the opener, and a summary with the credits used.
GET https://programmable.info/x/live?request=Find the head of sales and write an opener about their hiring&format=json&domains={{Company website}}
Authorization: Bearer YOUR_API_KEYMore than one company: a second zap
Zapier waits about 30 seconds for a step to answer, and a run stops when the step that started it stops waiting. So anything beyond one company comes back through a second zap that starts with Catch Hook, instead of waiting in the step.
- 1Make a zap that starts with Webhooks by Zapier, Catch Hook, and copy its URL.
- 2Paste it as your webhook in the app (Developers, Webhooks), or add it to the agent's link as
webhook=for that agent only. - 3Run the agent on its schedule or from the app. Rows arrive at the Catch Hook in batches as they finish (event
sheet.rows), then a summary (sheet.completed). - 4Each batch is signed with X-Programmable-Signature and carries an X-Programmable-Id that stays the same across retries, so duplicates are easy to drop.
An HTTP Request node
- 1After your trigger (a schedule, a new CRM record, a Sheets row), add an HTTP Request node.
- 2Method GET, URL the agent's link. Authentication: Generic, Bearer Auth, with your API key. Add the query parameter
domainsas an expression from the item before, like{{ $json.website }}. - 3n8n waits as long as the node's Timeout option allows, so a run for a handful of companies can come back in the same node. Raise the timeout for longer runs.
- 4The JSON has one item per row, ready for the next node: Slack, your CRM, a sheet.
Or send a POST body
The same request as JSON, for when the companies come as a list. Send Body: JSON. Rows are built when you ask and not stored; the response is the only copy.
POST https://programmable.info/api/sheet
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"domains": ["{{ $json.website }}"],
"format": "json"
}For long lists, set a Webhook trigger node's production URL as your webhook in the app and let the rows arrive there in batches.
HTTP, Make a request
- 1After the module that has the company, add HTTP, Make a request.
- 2URL: the agent's link. Method GET. Header
Authorization:Bearer YOUR_API_KEY. Query stringdomainsmapped from the module before. - 3Tick Parse response so the rows come out as bundles for the next modules.
- 4Make stops waiting at the module's timeout, and the run stops with it. Keep a step to a few companies, or use a webhook for more.
Long runs: a Custom webhook scenario
Start a second scenario with Webhooks, Custom webhook, and paste its address as your webhook in the app or as webhook= on the agent's link. Each batch of rows arrives as it finishes, signed, with a stable id per batch.
Tools that reach Airtable, Pipedrive or anything else work the same way: Programmable is one ordinary HTTP step, with no app to install.
Link recipes
Optional, and there when you need it: the companies, people, columns and your own questions all fit in one link. Open it anywhere and it builds the sheet again, fresh. Make one in the app, or write it yourself. Links you type in a browser while signed in run at once; a link someone else sends you shows the cost and a Run button first.
Any list of companies
A row per company: what they do, tech stack, mail setup, security, socials, leadership, hiring, news and more.
Ask your own questions
Each question becomes a column, answered from the company's own pages, with a one-line reason. Runs on your AI key.
People from a LinkedIn URL
Name, title, company and a work email, checked. With Apollo, Hunter, Findymail or PDL connected, the profile alone is enough.
Find people at companies
The sales leaders at each company, as a people sheet with emails. From your connected provider, or from the company's own team pages, included.
Pick columns in plain words
Only what you asked for. Write group names the way they read (or use exact column keys).
Unlock emails and mobiles
Spends your own provider credits only when you say so. Leave reveal out and nothing is unlocked.
Products, prices and stock
A row per product: price, sale price, stock, SKU and barcode, variants and ratings, from the store's own product data. Or give a store to list its products.
One formula per row in Google Sheets
Fill it down next to your list: every row enriches itself. Use your API key, or a limited share key made for the link.
Google Sheets
Put a link in an IMPORTDATA formula and the sheet enriches itself, one row per cell of websites. With header=0 each formula fills its own row without repeating the column names.
- Sheets recalculates now and then. With an agent that only takes new companies, each refresh returns only what it hasn't covered, so copy out what you keep or let the agent send it to your CRM.
- A key in a cell can be seen by anyone who can see the sheet: use a share key locked to the link, with a row and AI cap.
- Prefer formulas by name? The Sheets add-on gives PROGRAMMABLE(), PROGRAMMABLE_ROW() and PROGRAMMABLE_EMAIL(), cached for six hours so recalculating doesn't spend credits again.
=IMPORTDATA("https://programmable.info/x/live?key=YOUR_SHARE_KEY&header=0&domains="&ENCODEURL(A2))=PROGRAMMABLE_ROW(A2, "company, tech stack, hiring")
Setup for the add-on is in the API docs.
API basics
- Endpoint
POST https://programmable.info/api/sheet- Live links
GET https://programmable.info/x/live?…- Authentication
- An API key in
Authorization: Bearer …, made in the app under Developers. Share keys work for opening a link, not for the API. - Response
- CSV by default, JSON with
format=json, or a stream of events withAccept: application/x-ndjson. The summary carries the credits charged and what each destination did. - Webhooks
- Rows POSTed in batches while a run streams (
sheet.rows, thensheet.completed), signed with HMAC-SHA256. HTTPS only. - AI tools
- Also an MCP server at
https://programmable.info/api/mcpfor Claude, Cursor and other assistants, with the same key, credits and limits. - Errors
- Plain messages: 401 for a key it doesn't know, 402 when credits run out, 428 for a sentence not yet confirmed, 429 when you're over the hourly limit.
Every body field, the link parameters and each error are in the API docs. Keys, links and the webhook live in the app under Developers.
Questions
Do I need an app in Zapier, n8n or Make?
No. An agent is an ordinary HTTP request: Webhooks by Zapier, n8n's HTTP Request node or Make's HTTP module. There's nothing to install and no SDK to learn.
What happens the first time a sentence runs?
A plain-English request is read into a plan once and you confirm it in a browser; from a tool, an unconfirmed request answers 428 with a link to open. After that the plan is pinned to your account, so the same sentence runs the same way every time and planning costs nothing more. Change the wording and it's read and confirmed again, so keep the sentence fixed and pass the company in domains.
Which key goes in the tool?
An API key from Developers in the app, in the Authorization header, for HTTP steps. For a link that lives in a spreadsheet cell, make a share key instead: it can be locked to one link, capped in rows and AI spend, and allowed or not to send to your tools.
What does a call cost?
The same credits as in the app: one per researched row, plus one for each heavier group the agent asks for (email finder, leadership, mobile speed, marketplaces), and one per person found by Find people. AI questions and your own provider keys add nothing. Rows that fail are refunded.
Do I have to encode the URL?
No. Type spaces, commas and question marks as you'd write them; tools and browsers handle the rest. Avoid & and # inside a value (and + means a space). In Google Sheets, wrap cell values in ENCODEURL().