nodeTypes for platform-action and http, and triggerTypes for webhook. Note the URL of each type's schema; every option below comes from it.GET /catalog returns platformActionFields.get and platformActionFields.post, each entry carrying the key the step stores, the label the platform stores beside it, and whether the field is builtin or custom. A key outside those lists is stored as sent and POST /{workflowId}/validate reports UNKNOWN_USER_FIELD as a warning, but the step reads or writes nothing, so take the key from the catalog.apiKey.enabled: true and no value, and keep the key from this response: no later read shows it again.201, status: draft, trigger.type: webhook, a revision, and trigger.options.apiKey.value present. That value is your sender's credential. Store it somewhere secret and do not paste it into a document.tokenExchangeEnabled is the other supported mode: the sender first exchanges the workflow key for a short session and sends that instead. Choose one mode and tell the sender which. The sender's side, the key exchange, sending the event and reading back the result, is covered in Workflow webhooks.trigger._id from the create response, and the payload field is read from the trigger's root. The read keys total_xp and total_coins below come from the catalog's get list:201 with the step, its _id and the new revision. That _id is what later steps reference.AND: an OR or WHERE group is stored and deployed, and the runtime then treats it as always true, so validation reports ROUTER_OPERATOR_UNSAFE.0 of that router (65f1a2b3c4d5e6f708192a3e):logic: add is what makes the reward cumulative. overwrite replaces the value with the amount, which is almost never what a reward means. The write key xp comes from the catalog's post list; a custom field would appear there with its own key and label.GET /{workflowId} shows three steps and the write step nested under the first branch.executed, the write step is simulated with wouldDo naming the member, the field xp, the amount 100 and the logic add, and sideEffects: "none".wouldDo.users list is the member the platform resolved, so an empty list means the identifier did not resolve.GET /runs/{runId} for that run, then read the member's field through the platform API. The run result and the member's value together are what settle it; a 200 from the trigger call alone shows only that the call was accepted.| What you see | What it means | What to do |
|---|---|---|
401 from the webhook call | Wrong key, or the trigger was replaced after the sender was configured | Read the trigger: a stored key is never shown again, and a PUT cannot replace it. Set the trigger to another type and back to mint a new key, then update the sender. |
| Deploy went through with warnings you did not read | Validation is advisory, so no validation finding refuses a deploy; the response's warnings list what a run may mishandle | Fix the named steps, then validate again and compare the two reports. |
Run error with User not found | The identifier the event carried does not resolve to a member | Check the sender's field, then the read step's binding. |
Run success, member value unchanged | The write step was skipped, or the amount was zero | Read the run detail and check the branch that ran. |
| Two awards for one event | The sender sent the event twice and the workflow has no duplicate guard | Fix deduplication at the sender, then reconcile the extra award through your own reversal process. |
POST /runs/{runId}/retry runs the whole workflow again and can pay twice. It needs no confirmation, so read the member's value before retrying, and send an Idempotency-Key so a lost response replays instead of queueing a second run.