Set up an action
Add any of the catalog's actions to an agent, choose who performs it, and connect its API the way that API takes its key.
An action is one thing an agent may do: send a Gmail message, create a Trello card, refund a Stripe charge. Each becomes a tool on the agent, and every call to it runs Veefore's policy, risk and approval first. This page is how to set one up. The actions catalog lists every action, app by app, with the exact call and what to enter.
#The steps
Add it
Integrations → n8n, choose the agent, then Add tools:
- Browse apps: pick an app, or search ("trello create card", "stripe refund"). No model is involved.
- Describe the agent: Veefore's model picks actions from the catalog. It only chooses; it cannot invent a field or an endpoint.
- Import OpenAPI: any API with an OpenAPI 3 or Swagger 2 document.
Tick the actions and Add. Each joins the list as a row.
Choose who performs it
Each row has a switch: n8n or Veefore.
- n8n performs it: Veefore decides; the n8n node you connect to the Veefore node's Allowed output does the work, with the credential you keep in n8n. The row names that credential and links n8n's page on it.
- Veefore performs it: Veefore decides and then makes the call itself, with a key sealed in its broker. n8n never holds the key, and a refused call cannot happen.
Apps that are not a web API (databases, queues, file transfer, local steps), or whose requests Veefore cannot sign, offer only n8n. The row says why.
Enter the key
For Veefore performs it, the row asks for what it still needs. One value (a token, an API key) fits in the row; Get a … key opens the provider page where it is issued. When an API needs more than one value (a username and password, a token and an account ID, an OAuth client), the row says what and Enter them opens the editor.
The endpoint is already filled in. If its host has a {placeholder}
(https://{subdomain}.zendesk.com/…), Edit endpoint and put in your own.
Save and try it
Save creates the tools. Try a decision runs your policy against a sample call without performing it. Then connect n8n with the Key ID and connection secret (n8n).
#Where each endpoint comes from
The endpoint is the call n8n itself makes for that action, so "Veefore performs it" does exactly what the n8n node would:
| Source | For |
|---|---|
| The provider's OpenAPI document | The API actions (Claude, Gemini, Groq, Resend, Stripe, Twilio, SendGrid, Slack, Discord, Asana, GitHub, Intercom, Brevo) and anything you import. Fields, types, required values and placement are the spec's, and every call is checked against them before it is sent. |
| n8n's node definition | Declarative nodes, which state the method and URL in data. |
| n8n's node source | Nodes that make their calls in code. The source is read without running it: the method, the URL template and which field fills each {placeholder}. |
| Reviewed per action | Calls built at run time (Microsoft Teams meetings, Excel workbooks, Odoo, the AWS services, GraphQL APIs). Each was written from that action's code in n8n and the provider's reference. |
Where none of these gives an exact call, the action is n8n performs it only, rather than a guessed endpoint.
n8n's field names
An action from n8n's catalog carries the n8n node's fields under n8n's names
(sendTo, subject). When Veefore performs it, those fields are what it
sends, and some APIs name them differently. If the provider rejects a call
for a field, use the provider's API action from the catalog (its fields are
the API's own, and checked) or import its OpenAPI document.
#How the key is sent
Each app takes its key in its own way, and the catalog knows which. You only enter the values; Veefore places them. The catalog shows it for every app.
| The API takes | You enter | For example |
|---|---|---|
A bearer token (Authorization: Bearer …) |
The token | Notion, Matrix, OpenAI, Coda |
| A key in a header, maybe with a prefix | The key | Anthropic (x-api-key), DeepL (DeepL-Auth-Key …), PagerDuty (Token token=…), MessageBird (AccessKey …) |
| A key in the query string | The key | Pipedrive (?api_token=), Hunter, NASA, OpenWeatherMap, Yourls |
| A key in the request body | The key | UptimeRobot, Vonage, Mandrill, Paddle, PostHog |
| A key in the URL path | The key | Telegram (/bot<token>/…), SIGNL4 |
| Username and password (basic auth) | What the API calls them | Zendesk (your email followed by /token, and the API token), Jira, WooCommerce |
| Basic auth with the key alone | The key | Chargebee and Onfleet (key as username), Lemlist and Affinity (key as password), Freshservice (password fixed to X) |
| OAuth 2.0 | The OAuth app's client ID and secret, and a refresh token | Gmail, Microsoft Teams and Outlook, Webflow, Google Sheets |
| An AWS access key | Access key ID, secret access key, region | Every AWS action |
#Values beside the key
Some APIs want a second value with every call. The editor asks for it and says where it goes:
| App | Beside the key |
|---|---|
| Harvest | Account ID, in the Harvest-Account-Id header |
| Trello | API token, in the query beside the key |
| Discourse | Username, in Api-Username |
| Quick Base | Realm hostname, in QB-Realm-Hostname |
| Netscaler ADC, RocketChat, Salesmate, Demio, Vonage, Mocean, Paddle | A user, user ID, domain, secret or vendor ID |
Fixed values (Copper's X-PW-Application: developer_api) and a key the API
wants twice (Supabase's apikey beside its bearer token) need nothing from
you; the editor shows what else is sent.
#OAuth
Veefore keeps the refresh token and renews access tokens itself, so the tool keeps working after the first one expires. Create an OAuth app with the provider, authorize it once with offline access, and paste the client ID, client secret and refresh token. The token URL and scope come from n8n's definition of that app's OAuth credential. For Google, Google's OAuth Playground gives a refresh token for your own client.
#AWS
Veefore signs each request with Signature Version 4. The region you choose
moves the endpoint (dynamodb.eu-west-1.amazonaws.com). JSON APIs (DynamoDB,
Cognito, Comprehend, Transcribe, Certificate Manager, Textract, Rekognition)
name the operation in X-Amz-Target; query APIs (IAM, SES, SNS, SQS, ELB)
take Action and Version in the URL with the fields form-encoded. S3 uses
path-style URLs (s3.us-east-1.amazonaws.com/<bucket>/<key>). Use an IAM user
or role limited to what the agent needs.
#Special shapes
| Shape | What to know |
|---|---|
| GraphQL APIs (Monday.com, Linear, Emelia) | One endpoint. The tool takes a query document and its variables, so the agent writes the GraphQL for the action. |
| Your own host | Self-hosted and per-account apps (Zendesk, Mautic, NocoDB, Odoo, Nextcloud) have {subdomain} or {host} in the endpoint. Put in yours; a placeholder can never stay in the host. |
| Path fields | {field} in the path is filled from the field of that name, encoded, so a value can never change the host or add a segment. |
| Fixed protocol headers | Headers an API needs on every call (Notion-Version, anthropic-version, Travis-API-Version) are sent for you. They can never carry or replace a credential. |
#What Veefore guarantees about the key
- It is sealed in the broker when you save, and never shown or returned again.
- It is placed only after the call's host has passed the tool's destination check, and redirects are refused, so a key reaches only its own API.
- A field the caller sends with the same name as the key (
?key=…) is replaced by the key, never the other way round. - A credential can never set the
Host, framing or Veefore's own headers, a line break in a header, or the same value twice. Such a credential is refused when it is saved. - The key and the values beside it never appear in a response, a log or the audit trail.
#Only n8n can perform these
| Why | Apps |
|---|---|
| Not a web API | Postgres, MySQL, MongoDB, Redis, Kafka, RabbitMQ, MQTT, FTP, Send Email (SMTP), Crypto, JWT, TOTP and other local steps |
| Each request is signed with another scheme | Azure Storage, Azure Cosmos DB (shared key), Unleashed (HMAC), S3-compatible servers |
| The key is first exchanged for a short-lived token | Bitwarden, HaloPSA, PayPal, Taiga, SeaTable, FileMaker, Google service accounts |
| The action needs several calls | "Send and wait for a reply" in Gmail, Slack, Telegram and others; Excel and Google Sheets update and upsert |
| The call has a shape Veefore does not send | Nextcloud files (WebDAV), Firebase Realtime Database paths, Todoist reminders (Sync API command batches), file uploads |
The full list, with the reason for each, is in the catalog index.
#Troubleshooting
| Symptom | Cause |
|---|---|
| Saving: "A credential cannot set the … header" | The header is reserved (Host, Content-Length, Veefore's own). Use the header the API documents. |
| Saving: "… is placed twice" | Two values go to the same header or parameter. Remove one. |
The call fails with the provider's 401 |
The key is wrong, or for basic auth the username and password are swapped. The catalog says which value goes where for each app. |
| "This credential goes in the request body, and a GET request has none" | The API takes its key in the body, and the endpoint was changed to GET. Use the method the catalog lists. |
| The provider rejects a field | n8n's field names differ from the API's. Use the provider's API action or import its OpenAPI document. |
OAuth: invalid_grant |
The refresh token was revoked or was issued for another client. Authorize again with offline access. |
AWS: SignatureDoesNotMatch |
The secret access key is wrong, or the region does not match the endpoint. |