An API trigger’s key answers “is this call allowed to fire?” It says nothing about who made it. If you expose a workflow to a web app, a partner, or your own backend, you often need to know the actual end user — and you need that identity to be something the caller cannot forge.
Verified Inputs lets a caller attach a JWT from an identity provider you’ve registered. Pinkfish verifies the signature, then hands the validated claims to your workflow as a _verified input.
Verified Inputs establishes who is calling. It does not change whose connections run — the workflow still executes with the trigger owner’s connections. See Tool Sharing and Identity.
How a call is authenticated
Two independent things travel on the request:
| What | Header | Answers |
|---|
| API key | X-API-KEY (or embedded in the webhook URL) | Is this call allowed to fire this trigger? |
| JWT | Authorization: Bearer <jwt> | Who is the end user making it? |
The API key remains required. The JWT is additional.
By default, verification is opportunistic: if a Bearer token is present and its issuer matches one of your registered providers, Pinkfish verifies it and injects the claims. If no token is present, the run proceeds without _verified. You can make it mandatory — see Requiring verification.
Registering a trusted identity provider
Go to Settings → Triggers and add a provider. Providers are scoped to your organization and can only be managed by an org admin.
| Field | Notes |
|---|
| Name | Your label for the provider. |
| Issuer | Must exactly equal the iss claim in the tokens you mint. |
| Audience | Set by Pinkfish, not by you — always org:<your-org-id>. Mint your tokens with this aud. |
| JWKS URL or PEM | Exactly one. A JWKS URL is strongly preferred, since it supports key rotation. Must be HTTPS. |
| Subject claim | Which claim identifies the user. Defaults to sub. |
| Allowed algorithms | Asymmetric only. HS* and none are always rejected. |
| Max token age | How old an iat may be. Defaults to 300 seconds. |
| Status | active or disabled. |
The audience is pinned to your organization on purpose. Because Pinkfish forces aud to org:<your-org-id>, a token minted for one organization cannot be replayed against another organization’s trigger. Your token issuer must set that exact aud value or verification fails with audience_mismatch.
Use the Test action on a provider to paste a sample JWT and see the resolved subject and claims before you wire anything up.
What the workflow receives
When verification succeeds, Pinkfish adds a top-level _verified key to the workflow’s inputs. Its value is the entire validated claim set — every claim the token carried, verbatim:
{
"customerId": "acme-42",
"_verified": {
"iss": "https://auth.example.com/",
"aud": "org:org_abc123",
"sub": "user_9f2c",
"email": "dana@example.com",
"exp": 1782000000,
"iat": 1781999700,
"role": "admin"
}
}
Branch on it like any other input — for example, use _verified.sub as the record owner rather than trusting a caller-supplied userId.
_verified cannot be spoofed. Pinkfish strips any caller-supplied _verified key from the inputs of every run-creation path — API, schedule, email, manual, and bulk — before it re-adds a genuinely verified one. A workflow default cannot reintroduce it either. If the key was present, the attempt is logged.So inside a workflow, the presence of _verified always means a real token verified against one of your registered providers.
Each run also records three immutable audit fields, surfaced as a “Verified caller” badge in the run details: whether a JWT was presented, the verified subject, and which provider validated it.
Requiring verification
Opportunistic verification means an unauthenticated caller still runs the workflow — just without _verified. To reject those calls outright, turn on requireVerifiedRequest for the trigger. The request is then refused before any run is created.
Turn on Require verified request — “Reject API requests that lack a verified Trusted-IdP identity (JWT). Off by default.” You’ll find it:
- On a workflow API trigger, in the trigger editor alongside the API key fields.
- On an agent API channel, in the agent editor’s Channels section.
It can also be set through the API — it’s a requireVerifiedRequest field on the trigger, and agent API channels have a dedicated endpoint (PUT /api/useragents/{userAgentId}/channels/api/require-verified-request).
If you rely on verified identity for authorization, you must turn this on. It is off by default, and while it is off a caller who simply omits the Authorization header gets a successful run with no _verified key at all — so a workflow that reads _verified.sub would see nothing rather than an error.
Failure responses
A token whose issuer matches a registered provider but which fails verification is always rejected with 401, whether or not verification is required. A missing token is rejected only when requireVerifiedRequest is on.
Responses follow the OAuth bearer-token convention:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="expired"
Content-Type: application/json
{ "error": "expired", "error_description": "JWT has expired" }
error | Meaning |
|---|
verification_required | The trigger requires a verified request and none was presented. |
unknown_issuer | No registered provider matches the token’s iss. |
signature_invalid | Signature does not verify against the provider’s keys. |
audience_mismatch | aud is not org:<your-org-id>. |
expired | The token’s exp has passed. |
token_too_old | The token’s iat exceeds the provider’s max token age. |
algorithm_not_allowed | The signing algorithm is not in the provider’s allowed list. |
invalid_token | The token is malformed. |
A Bearer token whose iss matches no registered provider is ignored rather than rejected, so an unrelated Authorization header won’t break a trigger — unless requireVerifiedRequest is on, in which case it counts as “no verified identity presented.”
Where it applies
| Surface | Verified Inputs |
|---|
| Workflow API triggers | Yes — verify, inject _verified, optional enforcement. |
| Agent API channels | Yes — the verified claims travel as metadata rather than workflow inputs. |
| Webhook triggers | No. Webhook deliveries authenticate by HMAC signature from the sending provider, so the JWT path is skipped and the payload is left untouched. |
| Schedule, email, app-event triggers | No JWT is verified. Any caller-supplied _verified is still stripped. |
Relationship to A2A end-user connections
Both features verify a caller’s JWT against the same trusted-provider registry, but they do different things with the result.
- Verified Inputs treats the identity as data. The run still executes with the trigger owner’s connections.
- A2A end-user connections treat the identity as an execution principal. Each external caller resolves connections against their own account, and the call is rejected if no verified identity is presented.
Reach for Verified Inputs when you want the workflow to know who asked. Reach for A2A end-user connections when each caller must act as themselves against the third-party app.