Skip to main content

Triggers

Triggers define how a flow is initiated. Every flow has exactly one trigger method, decorated with @HttpTrigger, @ManualTrigger, @RecurrenceTrigger, or @ConnectorTrigger.

Trigger options can be passed either as an argument to the decorator, or returned as an object literal from the trigger method body — both forms are supported, and body values take precedence over decorator arguments if both are given:

// Decorator argument form
@RecurrenceTrigger({ frequency: 'Day', interval: 1 })
trigger() {}

// Return-statement form (equivalent)
@RecurrenceTrigger()
trigger() {
return { frequency: 'Day', interval: 1 };
}

The decorator argument is type-checked against the options listed below. The options in Settings for every trigger and a few trigger-specific ones are read by the compiler but are not part of the typed decorator options, so write them in the return-statement form, as generated DSL does.

HTTP Trigger​

Starts the flow when an HTTP request is received.

@HttpTrigger({ method: 'POST' })
trigger() {}

Options (HttpTriggerOptions)​

  • method? — HTTP method (GET, POST, PUT, DELETE, PATCH, ...); defaults to POST when omitted
  • path? — relative path
  • schema? — JSON schema for the request body: { type, properties?, required? }

Also read from the return-statement form:

  • triggerKind? — 'Http' (the default) or 'VirtualAgent' for a flow called from Copilot Studio. A 'VirtualAgent' response needs this trigger kind (DSL044).
  • headersSchema? — JSON schema for the request headers
  • triggerAuthenticationType? — written to the trigger's inputs.triggerAuthenticationType in Logic Apps JSON

Manual Trigger​

Starts the flow via a manual invocation — the "Button" trigger in Power Automate, a Power Apps call, or a parent flow's "Run a Child Flow".

@ManualTrigger()
trigger() {
return {
schema: {
type: 'object',
properties: {
text: { type: 'string', title: 'Input', 'x-ms-dynamically-added': true },
},
required: [],
},
};
}

Options (ManualTriggerOptions)​

  • schema? — JSON schema for trigger inputs: { type, properties?, required? }

Also read from the return-statement form:

  • triggerKind? — 'Button' (the default) or 'PowerAppV2' ("When Power Apps calls a flow (V2)")
  • headersSchema?, triggerAuthenticationType? — as for the HTTP trigger

A 'PowerApp' response (ctx.response(..., 'PowerApp')) belongs with this trigger (DSL044).

tip

For inputs to appear in the Power Automate maker portal designer, every property under schema.properties must include "x-ms-dynamically-added": true. Without it, the designer silently hides the input (the flow still runs, but makers can't see/edit the parameter).

Recurrence Trigger​

Starts the flow on a schedule.

@RecurrenceTrigger({
frequency: 'Day',
interval: 1,
timeZone: 'Eastern Standard Time',
schedule: { hours: [9], minutes: [0] },
})
trigger() {}

Options (RecurrenceTriggerOptions)​

  • frequency — 'Second' | 'Minute' | 'Hour' | 'Day' | 'Week' | 'Month' | 'Year'
  • interval — number of frequency units between runs
  • timeZone? — e.g. 'Eastern Standard Time'
  • startTime? — ISO 8601 start time
  • schedule? — fine-grained schedule:
    • minutes?: number[]
    • hours?: number[]
    • weekDays?: ('Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday' | 'Sunday')[]
    • monthDays?: number[]

Rules Power Automate enforces on save​

The editor checks these as you type (DSL045, DSL046; RECURRENCE / RECURRENCE_SCHEDULE on JSON):

  • interval is a whole number, and the period is at most 500 days (for example at most 500 for Day, 71 for Week, 16 for Month, 1 for Year).
  • A schedule needs frequency Day, Week or Month.
  • weekDays needs frequency: 'Week'; monthDays needs frequency: 'Month'.
  • A scheduled recurrence must next run within 18 months, and startTime may be at most 49 years ahead.

A flow with a recurrence trigger has no caller, so it cannot use ctx.response() (DSL038). The same applies to a polling connector trigger.

Connector Trigger​

Starts the flow off a connector event, such as "when a SharePoint item is created" or "when a new email arrives."

/** @trigger When_an_item_is_created */
@ConnectorTrigger({
connector: 'sharepoint',
operation: 'GetOnNewItems',
params: {
dataset: 'https://contoso.sharepoint.com/sites/MySite',
table: '{list-guid}',
},
connectionReferenceName: 'shared_sharepointonline',
splitOn: '@triggerBody()?[\'value\']',
recurrence: { interval: 1, frequency: 'Minute' },
})
trigger() {}

Options (ConnectorTriggerOptions)​

  • connector — connector name (e.g. 'sharepoint', 'office365')
  • operation — the connector's trigger operation ID (e.g. 'GetOnNewItems', 'OnNewEmailV3')
  • params — operation-specific parameters (connector/operation dependent)
  • connectionReferenceName? — connection reference to use
  • splitOn? — property to split trigger results on, so the flow runs once per item
  • recurrence? — polling interval: { interval: number; frequency: string }. A trigger with a recurrence is treated as a polling trigger by the placement rules (no ctx.response(), DSL038).

Also read from the return-statement form:

  • triggerType? — the Logic Apps trigger type: 'OpenApiConnection', 'OpenApiConnectionWebhook' or 'OpenApiConnectionNotification' (the default when omitted). Use the type the operation has in Power Automate; DSL generated from an existing flow keeps the original.
  • authentication? — the authentication expression, usually "@parameters('$authentication')"
  • retryPolicy? — the trigger's retry policy (same rules as @retryPolicy)

Use the /** @trigger Name */ JSDoc comment above the decorator to control the generated trigger's name (otherwise it defaults to the operation name). @trigger also works on @RecurrenceTrigger (default name Recurrence). HTTP and manual triggers are always named manual.

Connector triggers are compiled into the flow definition but do not fire locally: to run such a flow, pass the event's payload as the trigger body with --in.

Dataverse row events​

The Dataverse "When a row is added, modified or deleted" trigger takes numeric codes. Write them with the built-in enums DataverseMessage, DataverseScope and DataverseRunAs (available in every .ff.ts file without an import); they compile to the numbers:

@ConnectorTrigger()
trigger() {
return {
connector: 'dataverse',
operation: 'SubscribeWebhookTrigger',
params: {
'subscriptionRequest/message': DataverseMessage.Added,
'subscriptionRequest/entityname': 'account',
'subscriptionRequest/scope': DataverseScope.Organization,
},
connectionReferenceName: 'shared_commondataserviceforapps',
triggerType: 'OpenApiConnectionWebhook',
};
}
EnumMembers
DataverseMessage (subscriptionRequest/message)Added (1), Deleted (2), Modified (3), AddedOrModified (4), AddedOrDeleted (5), ModifiedOrDeleted (6), AddedModifiedOrDeleted (7)
DataverseScope (subscriptionRequest/scope)User (1), BusinessUnit (2), ParentChildBusinessUnit (3), Organization (4)
DataverseRunAs (subscriptionRequest/runas)ModifyingUser (1), RowOwner (2), FlowOwner (3)

Settings for every trigger​

All four trigger decorators also read these settings from the return-statement form:

  • conditions? — trigger conditions, as [{ expression: '@...' }]. The flow only starts when every condition is true.
  • runtimeConfiguration? — for example { concurrency: { runs: 1 } } to allow one run at a time (1–100, TRIGGER_CONCURRENCY)
  • correlation? — the trigger's correlation settings, passed through to Logic Apps JSON
@ManualTrigger()
trigger() {
return {
triggerKind: 'PowerAppV2',
schema: {
type: 'object',
properties: {
text: { type: 'string', title: 'Input', 'x-ms-dynamically-added': true },
},
required: [],
},
conditions: [{ expression: "@not(empty(triggerBody()?['text']))" }],
runtimeConfiguration: { concurrency: { runs: 1 } },
};
}

A // comment or @description above the trigger method becomes the trigger's description.

Accessing Trigger Data​

Use ctx.triggerBody() or ctx.triggerOutputs() to access trigger input data within actions.

@Action()
async processRequest(ctx: FlowContext) {
await ctx.compose('Order_id', ctx.triggerBody()?.['orderId']);
await ctx.compose('Caller', ctx.triggerOutputs()?.['headers']?.['x-ms-user-email']);
}

The trigger outputs are { headers, body }: ctx.triggerBody() is the body, and ctx.triggerOutputs() has both. In a local run, the payload you pass with --in is the body. See Cloud Semantics for the exact shape, how to pass request headers, and raw form or multipart bodies.