-
-
Notifications
You must be signed in to change notification settings - Fork 528
NotificationAPI Support #1399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
NotificationAPI Support #1399
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1399 +/- ##
========================================
Coverage 99.65% 99.65%
========================================
Files 174 175 +1
Lines 22554 22886 +332
Branches 3587 3664 +77
========================================
+ Hits 22476 22808 +332
Misses 70 70
Partials 8 8
🚀 New features to boost your workflow:
|
80dde3c to
5f34b60
Compare
sahandseifi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fantastic and very close to v1. Added a few comments about rethinking the API call, from there we should be able to take over.
apprise/plugins/notificationapi.py
Outdated
| continue | ||
|
|
||
| # Store our content | ||
| uid, recipient = result.group("id"), result.group("target") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is in line with your library's standards, but ideally, the user should be able to pass all 3 params at once: id, email, and number.
E.g.
apprise -t "Test Title" -b "Test Message" 'napi://...@.../.../id:xyz/email:[email protected]'
Or in another way that you see fit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it... id is now somewhat of a delimiter. YOu can specify an email, id, and/or SMS # in any order you want... the second a second id is defined/detected, it sets up a new target that can be notified.
Also got 100% test coverage going too i this last push to this PR. Have a look at the test examples and let me know your thoughts (id:sms and id:email) are now just any combination of:
id/emailid/smsid/sms/emailsms/email/id
The above equates to a single target, where as this would equate to 2:
id/email/id/emailid/sms/id/smsid/sms/email/id/sms/emailsms/email/id/email/sms/id
Hopefully this makes sense
apprise/plugins/notificationapi.py
Outdated
| parameters = self.tokens.copy() | ||
|
|
||
| # Apply some defaults template values | ||
| parameters["appBody"] = body |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking that with this library, it's probably expected by the user that we bypass our templating engine and like your other plugins, the content is directly sent over SMS or email with the title/body specified without a templating layer.
In this case, the "parameters" field in the API body is not used, and instead, the request should look like below, directly providing the content of each channel:
{
type: 'order_tracking',
to: {
id: 'spongebob.squarepants',
email: '[email protected]',
number: '+15005550006'
},
email: {
subject: 'Your Krabby Patty Order is Ready!',
html: '<h1>Order Update</h1><p>Your order is ready for pickup!</p>',
senderName: 'Krusty Krab', (optional)
senderEmail: '[email protected]' (optional)
},
sms: {
message: 'Your Krabby Patty order is ready for pickup!'
}
inapp: { title, image (optional), url (optional) },
web_push: { title, message, icon (optional), url (optional) },
mobile_push: { title, message },
slack: { text, blocks (optional) }
}
E.g.
apprise -vv -t "title" -b "body" 'napi://....?channels=email,sms'
{
type: 'order_tracking',
to: {
...
},
email: {
subject: "title",
html: "body",
},
sms: {
message: title + '\n' + body
}
}
https://www.notificationapi.com/docs/reference/server#pass-content-directly-without-templates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've switched the default to message while still leaving the template functionality in place; can be changed using new mode= flag.
apprise/plugins/notificationapi.py
Outdated
| } | ||
|
|
||
| if self.channel != NotificationAPIChannel.AUTO: | ||
| _payload["forceChannels"] = [self.channel] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to remove/ignore all the other optional parameters such as forceChannels, options, cc, bcc, ...
Anything other than type, to, email/sms/... wouldn't be necessary for v1.
apprise/plugins/notificationapi.py
Outdated
| f"({entry}) is invalid.") | ||
| self.logger.warning(msg) | ||
|
|
||
| if channel is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the next comment (below), this wouldn't be necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for NotificationAPI notifications to Apprise, enabling users to send notifications through email, SMS, calls, push, and in-app channels using a single API integration.
- Adds new NotifyNotificationAPI plugin with comprehensive URL parsing and payload generation for both template and message modes
- Extends URL schema length limits from 12 to 32 characters to accommodate "notificationapi" schema
- Includes comprehensive test suite covering URL parsing, payload generation, and error handling
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| apprise/plugins/notificationapi.py | New plugin implementation for NotificationAPI service with support for multiple channels and modes |
| tests/test_plugin_notificationapi.py | Comprehensive test suite covering URL validation, payload generation, and error scenarios |
| apprise/utils/parse.py | Extended regex patterns to support longer schema names and added sort parameter to parse_list function |
| apprise/config/base.py | Updated URL detection regex to support longer schema names |
| pyproject.toml | Added NotificationAPI to keywords list for package discovery |
| packaging/redhat/python-apprise.spec | Updated package description to include NotificationAPI |
| README.md | Added NotificationAPI entry to supported services table |
| tests/helpers/rest.py | Enhanced error reporting in test helper for better debugging |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
3064eb0 to
084b098
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
apprise/plugins/notificationapi.py
Outdated
| body, title="", notify_type=NotifyType.INFO, **kwargs): | ||
| # Perform our post | ||
| self.logger.debug( | ||
| "NotifiationAPI POST URL: {} (cert_verify={!r})".format( |
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spelling of 'NotifiationAPI' to 'NotificationAPI'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "instance": TypeError, | ||
| }), | ||
| ("napi://client_id/client_secret/id/g@rb@ge/+15551235553/", { | ||
| # g@rb@ge enry ignored |
Copilot
AI
Oct 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spelling of 'enry' to 'entry'.
| # g@rb@ge enry ignored | |
| # g@rb@ge entry ignored |
| def parse_list(*args, cast=None, allow_whitespace=True): | ||
| def parse_list(*args, cast=None, allow_whitespace=True, sort=True): | ||
| """Take a string list and break it into a delimited list of arguments. This | ||
| funciton also supports the processing of a list of delmited strings and |
Copilot
AI
Oct 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spelling of 'funciton' to 'function' and 'delmited' to 'delimited'.
| funciton also supports the processing of a list of delmited strings and | |
| function also supports the processing of a list of delimited strings and |
| def url_identifier(self): | ||
| """ | ||
| Returns all of the identifiers that make this URL unique from | ||
| another simliar one. Targets or end points should never be identified |
Copilot
AI
Oct 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spelling of 'simliar' to 'similar'.
| another simliar one. Targets or end points should never be identified | |
| another similar one. Targets or end points should never be identified |
Description:
Related issue (if applicable): n/a
NotificationAPI Notifications
appImageUrlparameter)NotificationAPI lets you trigger email, SMS, calls, push, and in‑app notifications using a single API. The Apprise plugin supports the US, CA, and EU regional hosts. Configure the content once in NotificationAPI, then trigger it from Apprise by sending the notification type and recipient information, with optional merge‑tag parameters.
🛠️ Setup Instructions
order_tracking).toobject.+15005550006.✅ Apprise Support
Syntax
Valid URL forms:
napi://{ClientID}/{ClientSecret}/{Target}napi://{Type}@{ClientID}/{ClientSecret}/{Target}notificationapi://{...}(alias ofnapi://)Targets can be combined in a single path and are grouped by a leading id. Each
{Target}segment may be:useridor@userid)[email protected])+15551234567)Examples of grouped targets:
userid/[email protected]→ id + emailuserid/+15551234567→ id + SMSuserid/+15551234567/[email protected]→ id + SMS + emailParameter Breakdown
typeapprise.modemessageortemplate. Defaults tomessage.idsecrettoidassociated with themregionus(default),ca, oreuto select the API host.channelsemail,sms,inapp,web_push,mobile_pushand/orslack.fromccbcc:{key}parameters(e.g.,:orderId=123). It's important to prefix each one of these with a colon (:) for it to be correctly interpreted. This is only used ifmodeis set totemplate* Required when not already set in the URL path component.
NotificationAPI Default Parameters
Each NotificationAPI request sent through Apprise includes the following default parameters:
appBodyappTitleappTypeinfo,success,warning,failure).appIdapprise.appDescriptionappColorappImageUrlappUrlThese parameters are always included by Apprise in addition to any custom
:{key}={value}tokens you provide in your URL.These defaults are common across all Apprise plugins, in addition to the service‑specific parameters described above.
📦 Examples
Send to one email recipient by type and let NotificationAPI pick the channel:
Send the same notification to multiple recipients using path segments:
Force the SMS channel and set the region to Canada:
Set From, CC and BCC for an email:
Pass dynamic template tokens that your NotificationAPI template references:
Use a query‑only form, handy in YAML:
Minimal (id + email):
EU region + token substitutions
Setting From / CC / BCC / Reply‑To (email)
New Service Completion Status
keywordssection to includenotificationapi%global common_descriptionChecklist
tox -e lintandtox -e format).tox -e minimal).Testing
Anyone can help test this source code as follows: