.example, not
commented out. Your node names the credential it needs, and that name is all your YAML ever
holds.
Someone enters the real value once in Canvas. The platform stores it encrypted, and
hands it to your node at the moment it runs, and only to your node.
That is what makes a node safe to commit, and safe to hand to someone else. It is also what
makes it publishable: the same node runs in someone elseβs universe, against their account,
with nothing of yours in it.
A node that calls a public API declares no credential at all, and skips all of this.
A credential is not a permission
These two get confused constantly, because both look like βauthβ and both show up on the same node in a workflow. They answer opposite questions. Picture a refund step on a canvas.
The key is always there. Once an admin has entered it, every run of that node can spend
it, whoever set the run off. The credential never asks who is calling.
That is precisely why the second question exists. Nothing about holding the key limits who
may pull the trigger, so a node that does something serious has to say so separately.
Who Can Run It is that half.
Three steps
1. Describe the credential
One file per credential type, in the packageβscredentials/ folder. It describes the
shape, never a value.
credentials/exampleCredential.yaml
properties becomes the form someone fills in. displayName, description and
placeholder are what they read while doing it, so write them for a person who has your
service open in another tab. documentationUrl is the link to where the key comes from.
secret: true is the fieldβs whole security posture. Mark anything that grants access.
A base URL is not secret. A key is.
2. Ask for it
The node names what it needs ininterface.yaml.
interface.yaml
required: true and no credential selected tells you before it runs.
3. Use it
Reference the value in the call, by name.api/run.yaml
credentials.<name>.<field>: the name from interface.yaml, then the property
from the credential file.
Auth schemes
scheme names how the credential reaches the service. Each one is implemented by the
platform, so you pick one rather than assembling headers yourself.
awsSigV4 is what turns every AWS service into a node. The signature hashes the exact
bytes being sent, so it is computation rather than description, and the platform does it.
A key that belongs in a header of its own:
Testing with your own key
unoverse node test runs a node against the real service, so it needs a real key. It reads
yours from your own .env, and stores nothing.
The variable is the credential name and the field, in upper snake case, with any trailing
Credential dropped:
A missing one is named before anything runs, rather than surfacing as a 401 from the
service.
Your node sees only its own credential
A node receives the credentials it declared ininterface.yaml, and nothing else. A workflow
holding an OpenAI node and a HubSpot node keeps the two apart: neither can read the otherβs
key, whatever it writes.
So {{ credentials.hubspotCredential.apiKey }} inside a node that declared only
exampleCredential resolves to nothing. That is not a bug to work around. Declare what you
need, and reference what you declared.
Naming the credential also rules out a subtler mistake. A node that went looking for βthe
first thing with an apiKeyβ would find whichever credential came first, since
openAICredential, apolloCredential and hunterCredential all have one. It would work
alone and authenticate against the wrong service the moment a second credential joined the
workflow. {{ credentials.<name>.<field>}} names the credential, so the wrong one is never
reachable by accident either.
When it goes wrong
Next: Who Can Run It

