Workspace variables
Store workspace values and secrets — like the token for an HTTP Function — and discover your CRM's fields.
met.variables stores two things belonging to the workspace: value variables (configuration and secrets, such as the token for an external API) and the definitions of your CRM's custom fields. The first needs the variables:write scope to write; the second lets you discover which keys a contact accepts.
const met = new Met(key, { workspaceId });
Value variables
A variable is a name → value pair that lives in the workspace. set() upserts by name — creating or updating depending on whether it exists — which is the most convenient form.
await met.variables.set('my_api_token', 'sk_live_...', { encrypted: true });
const vars = await met.variables.list(); // never returns secrets in the clear
Mark encrypted: true for tokens and secrets: the value is stored encrypted and list() no longer returns it in the clear. If you prefer explicit operations by id, you have create, update and delete:
const v = await met.variables.create({
name: 'greeting',
value: 'Hello!',
description: 'Default text',
}); // POST /variables (variables:write)
await met.variables.update(v.id, { value: 'Welcome!' });
await met.variables.delete(v.id);
set()runs alist()to find the name; if you are going to write many variables in a row, go straight tocreate/updatewith the id you already have.
Token → HTTP Function
The headline use case: an HTTP Function resolves its authentication token by variable name, not in the raw. You store the token once and the Function references it with auth_workspace_variable; Meteor sends it as Authorization: Bearer <value> when calling your endpoint.
// 1. Store the secret (encrypted)
await met.variables.set('my_api_token', 'sk_live_...', { encrypted: true });
// 2. The Function references it by name
await met.functions.create({
name: 'check_price',
description: 'Looks up a product price in the external API',
http: {
url: 'https://api.example.com/price',
method: 'POST',
auth_workspace_variable: 'my_api_token',
},
});
That way the token is never written into the Function's definition. To rotate it, a single set() with the same name replaces it and every Function using it is up to date.
CRM field definitions
A contact's custom fields live in its data under the bare key (stage, amount); system fields carry a $ ($name, $status). To find out which keys exist and which options a select accepts, discover the catalog:
const defs = await met.variables.fieldDefinitions(); // variables:read
const stages = defs.find((d) => d.field_key === 'stage')?.options ?? [];
await met.contacts.update(42, { data: { stage: stages[0] } });
Each definition carries field_key, label, type (text · number · select · currency · date · …) and options. You can also manage them from code:
const field = await met.variables.createFieldDefinition({
field_key: 'stage',
label: 'Stage',
type: 'select',
options: ['New', 'Contacted', 'Closed'],
});
await met.variables.updateFieldDefinition(field.id, { options: [...field.options, 'Lost'] });
await met.variables.deleteFieldDefinition(field.id);
field_key and type cannot be edited: changing them would break the values already stored on your contacts. You only adjust label, description and options.
To read and write those values on each contact, see Contacts (CRM).