Skip to content

Return detailed delivery status for each URL when notifying by tags #1611

@hiennnguyennn

Description

@hiennnguyennn

The idea

Currently, Apprise.notify() returns a single bool. When notifying multiple targets (using tags), it is impossible to programmatically identify which specific URLs succeeded and which failed, or why they failed, without resorting to fragile log-parsing.
I propose adding a detailed flag to the notify() method. When enabled, it should return a list of results, where each element contains:
URL: The target endpoint (obfuscated).
Status: A boolean indicating success or failure.
Details: A "Rich Response" containing the raw error message, exception, or API response body from the upstream service.

Use-case

In high-volume notification systems (like a Celery-based hub), we need to implement granular logic. For example:
If a specific Telegram URL fails, we want to log the exact raw response from Telegram to see if it's a rate limit or an invalid token.
We need to know exactly which URLs were successful so we can mark them as "Sent" in our database and only retry the specific failed ones.
Current workarounds involving logging.Handler are not thread-safe and fail in highly concurrent environments.

Proposed change

Extend Apprise.notify(..., detailed=True) to return a list of objects.
Example structure:
Python
[
{
"url": "tgram://...",
"success": False,
"status_code": 429,
"message": "Rate limit reached. Retry after 30s",
"timestamp": "..."
},
{
"url": "slack://...",
"success": True,
"status_code": 200,
"message": "OK",
"timestamp": "..."
}
]

Compatibility impact

  • Would this be a breaking change? No
    If we add a new method or an optional argument to notify(detailed=True), it will not break existing implementations that expect a boolean return.

Alternatives considered

  • Log Scraping: Fragile, hard to maintain, and not thread-safe.
  • Manual Looping (External to Apprise): I tried to iterate through each URL and call notify() individually for each one. However, this is highly inefficient:
    It bypasses Apprise's internal optimizations for handling multiple targets.
    The overhead of re-initializing/resolving plugins for each call significantly slows down the throughput (especially when dealing with hundreds of targets).
    It makes the implementation code redundant and complex outside the library.
    A native implementation within Apprise would maintain performance while providing the necessary granularity.

Documentation impact

  • Does appriseit.com require updates for this change? Yes. The developer API documentation needs to explain the new return format.

Additional context

I am willing to contribute the code for this enhancement. Providing a list of detailed statuses makes Apprise much more powerful for enterprise-grade integrations where "Why it failed" is just as important as "If it failed."

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions