Tag Routing & Retry
Apprise tags do more than just group services — they can drive delivery order, fallback chains, and retry behaviour without changing a line of application code.
This page explains how to configure those features in your configuration files and how to control them at call time via the Python library or CLI.
Priority Tags
Section titled “Priority Tags”Every tag in a configuration file may carry a numeric priority prefix separated by a colon: N:tagname.
Lower numbers mean higher urgency — they are dispatched first.
# Priority 1 -- primary alert channels (highest urgency)1:alerts=slack://tokenA/tokenB/tokenC1:alerts=discord://webhook_id/webhook_token
# Priority 2 -- secondary channels (used only if priority 1 fails entirely)2:alerts=telegram://bottoken/chatid
# Priority 5 -- last-resort backup5:alerts=mailto://user:pass@example.comTags without a priority prefix default to priority 0 (highest possible urgency).
version: 1urls: # Priority 1 -- primary alert channels (highest urgency) - slack://tokenA/tokenB/tokenC: tag: 1:alerts
- discord://webhook_id/webhook_token: tag: 1:alerts
# Priority 2 -- secondary channels (used only if priority 1 fails entirely) - telegram://bottoken/chatid: tag: 2:alerts
# Priority 5 -- last-resort backup - mailto://user:pass@example.com: tag: 5:alertsTags without a priority prefix default to priority 0 (highest possible urgency).
How Dispatch Works
Section titled “How Dispatch Works”Escalation Mode (default)
Section titled “Escalation Mode (default)”When you trigger a tag without specifying a priority prefix, Apprise uses the escalation chain:
- Services are grouped by their configured tag priority.
- The lowest-numbered group (highest urgency) runs first.
- If every service in that group succeeds, the result evaluates as true immediately — the higher-numbered groups are never triggered.
- If any service in the group fails, Apprise escalates to the next priority level and runs that group.
# Fire all 'alerts' services using the escalation chain.# Priority-1 entries run first. If they all succeed, priority-5 entries# are never triggered.apobj.notify(body="Disk usage above 90%", tag="alerts")# CLI equivalentapprise --config=config.yml --tag="alerts" --body="Disk usage above 90%"This is useful for tiered alerting: send to your fast channel first; only page the on-call person if the fast channel is unavailable.
How Groups Form
Section titled “How Groups Form”All services that share the same tag name and the same priority number are treated as a single group. The group is considered successful only if every service in it succeeds. If any one service fails, Apprise escalates to the next-higher-numbered group immediately.
Tags without a numeric prefix default to priority 0 — the highest urgency level. This means you can mix plain and prefixed versions of the same tag to create an escalation chain without touching existing URL entries:
# Priority 0 (default, highest urgency) -- these two form the first groupabc=slack://tokenA/tokenB/tokenCabc=discord://webhook_id/webhook_token
# Priority 1 -- escalation fallback if the priority-0 group fails1:abc=telegram://bottoken/chatidversion: 1urls: # Priority 0 (default, highest urgency) -- these two form the first group - slack://tokenA/tokenB/tokenC: tag: abc
- discord://webhook_id/webhook_token: tag: abc
# Priority 1 -- escalation fallback if the priority-0 group fails - telegram://bottoken/chatid: tag: 1:abcWhen notify(tag="abc") is called against the above:
- The priority-0 group (Slack + Discord) runs first.
- If both succeed,
Trueis returned — Telegram is never contacted. - If either fails, Apprise escalates to the priority-1 group (Telegram).
Because tags without a prefix default to priority 0, the service definitions abc and 0:abc
are fully equivalent. Both place the service in priority group 0, and a filter of either "abc"
or "0:abc" will match services tagged with either form. If both forms appear in the same
configuration file, those services will always be dispatched together as a single group.
Exclusive Mode
Section titled “Exclusive Mode”When you specify a priority prefix in the filter, Apprise skips the escalation chain and notifies only the services whose matching tag carries exactly that priority.
# Trigger ONLY 'alerts' entries configured with priority 2.# Priority-1 and priority-5 entries are untouched.apobj.notify(body="Scheduled maintenance window", tag="2:alerts")# CLI equivalentapprise --config=config.yml --tag="2:alerts" --body="Scheduled maintenance window"| Filter value | Behaviour |
|---|---|
"alerts" | Escalation chain — highest priority (lowest number) first |
"2:alerts" | Exclusive — only priority-2 alerts entries |
"0:alerts" | Exclusive — only priority-0 entries; alerts and 0:alerts definitions are identical |
Multi-Chain Failure Behaviour
Section titled “Multi-Chain Failure Behaviour”When notify() runs multiple independent OR chains simultaneously, the default is to let every chain complete before returning — even if one chain has already failed. This ensures every configured service gets at least one attempt.
To instead stop all remaining escalation rounds as soon as any chain exhausts its priority groups without success, set abort_on_chain_failure=True on your AppriseAsset:
from apprise import Apprise, AppriseAsset
asset = AppriseAsset(abort_on_chain_failure=True)apobj = Apprise(asset=asset)
# ...add services...
# If the 'ops' chain fails entirely, Apprise stops immediately and does# not run any further escalation rounds for the 'security' chain.apobj.notify(body="Critical alert", tag=["ops", "security"])abort_on_chain_failure | Behaviour when a chain fails |
|---|---|
False (default) | All chains complete; every service gets a chance |
True | Remaining escalation rounds are skipped; the result is False |
Per-Service Retry and Wait
Section titled “Per-Service Retry and Wait”Each service can be configured with its own retry count and inter-retry delay. These are independent of the escalation chain and apply whenever a delivery attempt fails.
retry— number of additional attempts after the first failure (0 = no retries).wait— seconds to pause between attempts (decimals accepted; 0.0 = no pause).
Append ?retry=N and/or ?wait=S directly to the URL as query parameters.
# Retry up to 3 times, waiting 5 seconds between attempts1:alerts=slack://tokenA/tokenB/tokenC?retry=3&wait=5
# Retry up to 2 times with a 1.5 second wait1:alerts=discord://webhook_id/webhook_token?retry=2&wait=1.5
# Backup channel -- no retry needed (default behaviour)5:alerts=mailto://user:pass@example.comUse the retry: and wait: keys under each URL entry.
version: 1urls: # Retry up to 3 times, waiting 5 seconds between attempts - slack://tokenA/tokenB/tokenC: tag: 1:alerts retry: 3 wait: 5
# Retry up to 2 times with a 1.5 second wait - discord://webhook_id/webhook_token: tag: 1:alerts retry: 2 wait: 1.5
# Backup channel -- no retry needed (default behaviour) - mailto://user:pass@example.com: tag: 5:alertsAccepted values
Section titled “Accepted values”| Parameter | Type | Constraints | Default |
|---|---|---|---|
retry | int | 0 to 10 | 0 |
wait | float | 0.0 to 20.0; integers promoted to float | 0.5 |
Invalid values (negative numbers, non-numeric strings, inf, nan) are rejected and
fall back to the asset default (see Global Defaults below).
Per-Service Timeouts
Section titled “Per-Service Timeouts”Every service gets a time budget — if it (including all of its retries and waits) hasn’t
finished within that window, Apprise stops waiting on it rather than hanging forever. This
is separate from retry/wait above: a service can be given plenty of retries but still be
cut off if the whole thing is taking too long.
By default, each service gets 60 seconds. Set your own value with service_timeout on
AppriseAsset, or turn the limit off entirely with 0:
from apprise import Apprise, AppriseAsset
# Give every service 10 seconds instead of the default 60asset = AppriseAsset(service_timeout=10)apobj = Apprise(asset=asset)apobj.add("slack://tokenA/tokenB/tokenC")
apobj.notify(body="Quick health check")# CLI equivalent -- --service-limit (-SL) applies the same limit to every serviceapprise --service-limit 10 --body "Quick health check" \ "slack://tokenA/tokenB/tokenC"A service that runs out of time is reported with a TIMEOUT status instead of a plain
failure — see Notification Results for how to check this from Python.
| Parameter | Type | Constraints | Default |
|---|---|---|---|
service_timeout | int / float | 0 or more; 0 disables the limit | 60 |
Optional Services
Section titled “Optional Services”The optional flag marks a service as allowed to fail without failing the whole
notification. When optional=yes is set on a service, a delivery failure for that
service does not affect the overall result. The overall result still evaluates as
true if all required services succeeded.
Use this for endpoints that should receive the notification when they are available, but should not make the calling application treat the notification as failed.
Example: home-screen displays
Section titled “Example: home-screen displays”Suppose your home automation system has four Kodi screens tagged media. You want to show
a notification on whichever screens are currently on, but you do not want a delivery
failure on a sleeping screen to wake you up at 3 am by paging your on-call channel.
# All four screens are optional -- their unavailability is never an error.media=kodi://192.168.1.10media=kodi://192.168.1.11media=kodi://192.168.1.12media=kodi://192.168.1.13To mark them optional, append ?optional=yes to each URL:
media=kodi://192.168.1.10?optional=yesmedia=kodi://192.168.1.11?optional=yesmedia=kodi://192.168.1.12?optional=yesmedia=kodi://192.168.1.13?optional=yesversion: 1urls: - kodi://192.168.1.10: tag: media optional: yes
- kodi://192.168.1.11: tag: media optional: yes
- kodi://192.168.1.12: tag: media optional: yes
- kodi://192.168.1.13: tag: media optional: yes# Even if every screen is off, this result still evaluates as true.apobj.notify(body="Dinner is ready", tag="media")apprise --config=config.yml --tag="media" --body="Dinner is ready"How optional interacts with required services
Section titled “How optional interacts with required services”The flag is per-service. You can freely mix optional and required endpoints within the same tag group. The aggregate result follows these rules:
| Services in batch | Result |
|---|---|
| All required, all succeed | True (SUCCESS) |
| All required, one or more fail | False (FAILURE) |
| All required, one or more time out, and none fail | False (TIMEOUT) |
| All optional, all fail | True (SUCCESS) |
| All optional, all time out | True (SUCCESS) |
| All optional, all succeed | True (SUCCESS) |
| Mix of required and optional; required all succeed | True (SUCCESS) |
| Mix of required and optional; any required fail | False (FAILURE) |
| Mix of required and optional; required time out only | False (TIMEOUT) |
In short: optional failures and optional timeouts do not fail the overall result. Only a required service failure or timeout can make the result evaluate as false.
How optional interacts with retries
Section titled “How optional interacts with retries”Setting optional=yes does not skip the service or bypass its retry logic.
Delivery is still attempted, and if retry is greater than zero, Apprise will retry
the configured number of times before giving up. Only after all retry attempts have been
exhausted does Apprise check the optional flag and decide whether to absorb the failure.
# This service is attempted up to 4 times (initial + 3 retries) with a# 2-second pause between attempts. If all four attempts fail, the failure# is silently absorbed because optional=yes.media=kodi://192.168.1.10?optional=yes&retry=3&wait=2- kodi://192.168.1.10: tag: media optional: yes retry: 3 wait: 2Setting optional from Python
Section titled “Setting optional from Python”You can set the flag directly on any loaded service object, or pass it as a constructor argument when building service objects manually:
import apprise
apobj = apprise.Apprise()
# Option 1 -- URL query parameter (works with all config loaders)apobj.add("kodi://192.168.1.10?optional=yes")
# Option 2 -- set the attribute directly after loadingobj = apprise.Apprise.instantiate("kodi://192.168.1.10")obj.optional = Trueapobj.add(obj)
# Option 3 -- constructor keyword argumentfrom apprise.plugins.NotifyJSON import NotifyJSONsvc = NotifyJSON(host="192.168.1.10", optional=True)apobj.add(svc)
# All three result in the same behaviour: failures are silently absorbed.result = apobj.notify(body="Dinner is ready")print(result) # True even if every endpoint was unreachableMore examples
Section titled “More examples”Non-critical debug logger alongside a required alert channel:
# Required: the on-call engineer must always get paged.alerts=slack://tokenA/tokenB/tokenC
# Optional: log to the internal diagnostics channel if it is up,# but never treat its absence as a failure.alerts=json://diagnostics.internal/api/events?optional=yesversion: 1urls: # Required: the on-call engineer must always get paged. - slack://tokenA/tokenB/tokenC: tag: alerts
# Optional: log to the internal diagnostics channel if it is up. - json://diagnostics.internal/api/events: tag: alerts optional: yes# Returns True if Slack succeeded, regardless of the JSON logger state.apobj.notify(body="Database unreachable", tag="alerts")All-optional tag group — “best effort” broadcast:
# Notify all three displays if they are reachable; never fail if they are not.displays=kodi://192.168.1.10?optional=yesdisplays=kodi://192.168.1.11?optional=yesdisplays=kodi://192.168.1.12?optional=yesversion: 1urls: - kodi://192.168.1.10: tag: displays optional: yes
- kodi://192.168.1.11: tag: displays optional: yes
- kodi://192.168.1.12: tag: displays optional: yes# The result still evaluates as true, no matter how many displays responded.apobj.notify(body="Motion detected", tag="displays")Global Defaults via AppriseAsset
Section titled “Global Defaults via AppriseAsset”If you want every service in an Apprise session to share the same retry, wait, and
timeout defaults without editing each URL, set them on AppriseAsset:
from apprise import Apprise, AppriseAsset
asset = AppriseAsset( default_service_retry=2, # retry up to 2 more times on failure before giving up default_service_wait=3.0, # wait 3 seconds between retries service_timeout=10, # give up on a stuck service after 10 seconds)
apobj = Apprise(asset=asset)apobj.add("slack://tokenA/tokenB/tokenC")apobj.add("discord://webhook_id/webhook_token")
apobj.notify(body="Defaults applied to every service")Per-URL values (?retry= / ?wait= or YAML keys) override the asset defaults for that specific service only. All other services still use the asset defaults.
Per-Call Retry Override
Section titled “Per-Call Retry Override”A trailing :N on a tag filter value overrides the retry count for every matched service for that one call only. The service’s permanent configuration is not changed.
# Retry each matched service up to 5 times for this call onlyapobj.notify(body="Critical alert", tag="alerts:5")
# Exclusive priority-2 match AND up to 3 retries per serviceapobj.notify(body="Priority 2 only", tag="2:alerts:3")# CLI equivalentsapprise --config=config.yml --tag="alerts:5" --body="Critical alert"apprise --config=config.yml --tag="2:alerts:3" --body="Priority 2 only"The :N suffix follows the same validation rules as the retry URL parameter. Specifying it does not affect wait — each service still uses its own configured wait value between retries.
Per-Call Timeout Override
Section titled “Per-Call Timeout Override”Pass timeout= to notify() to cap how long this one call is allowed to take, from
start to finish — across every service it notifies. Unlike service_timeout (which is a
per-service budget set on AppriseAsset), timeout is a ceiling on the whole call.
# Cap this entire call at 30 seconds, regardless of the asset's own# per-service timeoutapobj.notify(body="Time-sensitive alert", timeout=30)# CLI equivalent -- --limit (-L) applies to the whole runapprise --limit 30 --body "Time-sensitive alert" \ "slack://tokenA/tokenB/tokenC"When both are set, whichever one is sooner wins for each service — timeout= never
extends a stricter service_timeout, and a generous service_timeout never overrides a
tighter timeout=.
from apprise import Apprise, AppriseAsset
# Each service normally gets up to 60 seconds (the AppriseAsset default)...apobj = Apprise(asset=AppriseAsset())apobj.add("slack://tokenA/tokenB/tokenC")
# ...but this call cuts every service off at 5 seconds instead.apobj.notify(body="Give up quickly this time", timeout=5)timeout defaults to 0, meaning “no call-level cap” — only the AppriseAsset
service_timeout applies. Negative values raise an error, the same way an invalid
service_timeout does.
Multi-tag OR and AND filters
Section titled “Multi-tag OR and AND filters”Apprise supports two ways to combine tag names in a single notify call.
| Pattern | Meaning | Example |
|---|---|---|
| OR — multiple separate tag values | Match services that carry any of the listed tags | Multiple --tag flags in the CLI; a list of tag strings in Python |
| AND — multiple tag names in one filter entry | Match only services that carry all of the listed tags | A single --tag "a, b" flag in the CLI; a nested list in Python |
When using OR, each tag name forms an independent escalation chain.
Every chain must find a fully-successful priority group before the result
evaluates as true. A :N retry suffix on any token applies only to services
matched by that token; other tokens are unaffected.
# OR -- devops services get retry=3; management services get retry=2.# Each tag's escalation chain runs independently.apobj.notify(body="Team alert", tag=["devops:3", "management:2"])# OR -- multiple --tag flags; each is an independent chain.apprise --config=config.yml \ --tag="devops:3" \ --tag="management:2" \ --body="Team alert"If devops-tagged services all succeed at their lowest priority group,
Apprise still dispatches the management chain — the two chains are
independent of each other.
When using AND, services must carry every tag in the group to be selected. All AND-matched services share one escalation chain.
# AND -- service must carry BOTH "devops" AND "management" to match.apobj.notify(body="Combined alert", tag=[["devops", "management"]])# AND -- comma-separated values inside a single --tag flag.apprise --config=config.yml --tag="devops, management" --body="Combined alert"Putting It All Together
Section titled “Putting It All Together”The following example combines all three features: priority-based escalation, per-service retry/wait, and a per-call retry override.
# --- Primary channels (priority 1) ---# Retry 2 times, 2 second wait between attempts1:alerts=slack://tokenA/tokenB/tokenC?retry=2&wait=21:alerts=discord://webhook_id/webhook_token?retry=2&wait=2
# --- Secondary channel (priority 5 -- fallback) ---# Single attempt is enough here; the primary channels already retried5:alerts=mailto://user:pass@pagerduty.example.comversion: 1urls: # Primary channels (priority 1) - slack://tokenA/tokenB/tokenC: tag: 1:alerts retry: 2 wait: 2
- discord://webhook_id/webhook_token: tag: 1:alerts retry: 2 wait: 2
# Secondary channel (priority 5 -- fallback) # Single attempt; primary channels already retried - mailto://user:pass@pagerduty.example.com: tag: 5:alertsfrom apprise import Apprise, AppriseConfig
config = AppriseConfig()config.add("config.yml")
apobj = Apprise()apobj.add(config)
# Normal alert -- escalation chain# Slack and Discord (priority 1) run first; each retries up to 2 times# with a 2 second pause. If both succeed, PagerDuty (priority 5) is skipped.apobj.notify(body="Disk usage at 90%", tag="alerts")
# Critical incident -- retry each service up to 5 more times on failureapobj.notify(body="Database unreachable", tag="alerts:5")
# Maintenance window -- target only the email backup channel (priority 5)apobj.notify(body="Scheduled downtime in 30 min", tag="5:alerts")# Normal alert -- escalation chainapprise --config=config.yml --tag="alerts" \ --body="Disk usage at 90%"
# Critical incident -- retry each service up to 5 more times on failureapprise --config=config.yml --tag="alerts:5" \ --body="Database unreachable"
# Maintenance window -- target only the email backup channel (priority 5)apprise --config=config.yml --tag="5:alerts" \ --body="Scheduled downtime in 30 min"What happens step by step for the normal alert:
- Apprise finds all services tagged
alertsand groups them by priority. - Priority 1 group (Slack + Discord) dispatches first.
- Each service makes up to 3 attempts (initial + 2 retries), pausing 2 seconds between each.
- If both succeed —
Trueis returned; priority 5 is never triggered. - If either fails after all retries — Apprise escalates to priority 5.
- Priority 5 group (PagerDuty email) runs as a fallback.
Variations
Section titled “Variations”The examples below show common notification patterns using the features described on this page.
Single tag with two escalation levels — priority values 2 and 50 are used to
show that the numbers are arbitrary; only the ordering matters.
# First to try (lower number = higher urgency)2:alerts=slack://tokenA/tokenB/tokenC
# Fallback; only runs if priority 2 fails50:alerts=mailto://user:pass@example.comversion: 1urls: - slack://tokenA/tokenB/tokenC: tag: 2:alerts
- mailto://user:pass@example.com: tag: 50:alerts# Escalation chain: Slack first, email only on failureapobj.notify(body="Alert", tag="alerts")apprise --config=config.yml --tag="alerts" --body="Alert"Three OR chains each with multiple priority levels — alpha, beta, and gamma
are independent chains dispatched simultaneously. Within each chain, lower-numbered
groups run first; failures escalate to the next level. By default, every chain runs to
completion even after another chain has already exhausted all its levels without success
— see Multi-Chain Failure Behaviour above for how to
change this.
# alpha: three levels with arbitrary priority values1:alpha=slack://tokenA/tokenB/tokenC1:alpha=mailto://user:pass@gmail.com5:alpha=telegram://bottoken/chatid700:alpha=discord://webhook_id/webhook_token
# beta: single level at priority 500500:beta=discord://webhook_id2/webhook_token2
# gamma: two levels; no prefix means priority 0 (highest)gamma=telegram://bottoken2/chatid2200:gamma=telegram://bottoken3/chatid3version: 1urls: # alpha -- three escalation levels - slack://tokenA/tokenB/tokenC: tag: 1:alpha - mailto://user:pass@gmail.com: tag: 1:alpha - telegram://bottoken/chatid: tag: 5:alpha - discord://webhook_id/webhook_token: tag: 700:alpha
# beta -- single level - discord://webhook_id2/webhook_token2: tag: 500:beta
# gamma -- two levels (no prefix = priority 0) - telegram://bottoken2/chatid2: tag: gamma - telegram://bottoken3/chatid3: tag: 200:gammaDispatch order when all three chains are OR-ed together:
| Round | alpha | beta | gamma |
|---|---|---|---|
| 1 | Slack + Gmail (priority 1) | Discord (priority 500) | Telegram 2 (priority 0) |
| 2 (if round 1 failed for that chain) | Telegram (priority 5) | — exhausted — | Telegram 3 (priority 200) |
| 3 (if round 2 failed for alpha) | Discord (priority 700) |
All three chains run their round-1 batches simultaneously. By default, beta
exhausting in round 2 does not stop alpha or gamma from continuing their own
escalation rounds — each chain runs independently to completion, exactly as shown in
round 3 above.
apobj.notify(body="Broadcast", tag=["alpha", "beta", "gamma"])apprise --config=config.yml \ --tag="alpha" \ --tag="beta" \ --tag="gamma" \ --body="Broadcast"Two independent OR chains with per-call retry overrides — each tag token in the
filter carries its own :N retry suffix so devops services get three retries and
management services get two, all in one notify() call.
10:devops=slack://tokenA/tokenB/tokenC10:management=discord://webhook_id/webhook_tokenversion: 1urls: - slack://tokenA/tokenB/tokenC: tag: 10:devops
- discord://webhook_id/webhook_token: tag: 10:management# devops services get retry=3; management services get retry=2apobj.notify(body="Team alert", tag=["devops:3", "management:2"])apprise --config=config.yml \ --tag="devops:3" \ --tag="management:2" \ --body="Team alert"AND filter — only services that carry every listed tag are dispatched.
# Both tags on the same URL; only this service matches the AND filterdevops management=slack://tokenA/tokenB/tokenC
# Only "devops" -- will NOT match an AND filter requiring bothdevops=discord://webhook_id/webhook_tokenversion: 1urls: # Both tags on the same URL; only this service matches the AND filter - slack://tokenA/tokenB/tokenC: tag: - devops - management
# Only "devops" -- will NOT match an AND filter requiring both - discord://webhook_id/webhook_token: tag: devops# AND -- service must carry BOTH "devops" AND "management"apobj.notify(body="Combined alert", tag=[["devops", "management"]])# AND -- comma-separated values inside a single --tag flagapprise --config=config.yml --tag="devops, management" --body="Combined alert"Exclusive dispatch — a priority prefix in the filter targets only that exact priority level. No escalation chain is built; the matched services are dispatched as a single flat batch.
2:alerts=slack://tokenA/tokenB/tokenC50:alerts=mailto://user:pass@example.comversion: 1urls: - slack://tokenA/tokenB/tokenC: tag: 2:alerts
- mailto://user:pass@example.com: tag: 50:alerts# Exclusive: only priority-50 entries run; Slack (priority 2) is skippedapobj.notify(body="Maintenance window", tag="50:alerts")apprise --config=config.yml --tag="50:alerts" --body="Maintenance window"Summary
Section titled “Summary”| Feature | Where it is set | Scope |
|---|---|---|
| Tag priority | N:tagname in config file (TEXT or YAML) | Per service definition |
| Per-service retry count | ?retry=N URL param or YAML retry: key | Per service definition |
| Per-service retry wait | ?wait=S URL param or YAML wait: key | Per service definition |
| Optional service flag | ?optional=yes URL param or YAML optional: yes key | Per service definition |
| Per-service timeout | AppriseAsset(service_timeout=N) or --service-limit N | Per service definition |
| Global retry/wait defaults | AppriseAsset(default_service_retry=N, default_service_wait=S) | All services in the session |
| Escalation dispatch | notify(tag="tagname") or --tag tagname (no priority prefix) | One notify() / CLI call |
| Exclusive dispatch | notify(tag="N:tagname") or --tag N:tagname | One notify() / CLI call |
| Per-call retry override | notify(tag="tagname:N") or --tag tagname:N | One notify() / CLI call |
| Per-call timeout override | notify(timeout=N) or --limit N | One notify() / CLI call |
| Multi-tag OR dispatch | notify(tag=["tagA", "tagB"]) or --tag tagA --tag tagB | One notify() / CLI call |
| Multi-tag AND dispatch | notify(tag=[["tagA", "tagB"]]) or --tag "tagA, tagB" | One notify() / CLI call |
| Multi-tag OR with per-tag retry | notify(tag=["tagA:N", "tagB:M"]) or --tag tagA:N --tag tagB:M | One notify() / CLI call |
| Early-abort on chain failure | AppriseAsset(abort_on_chain_failure=True) | All services in the session |
Questions or Feedback?
Technical Issues
Having trouble with the code? Open an issue on GitHub: